diff --git a/etc/benchmarks/main.mjs b/etc/benchmarks/main.mjs
index 8fd6d858..e6530891 100644
--- a/etc/benchmarks/main.mjs
+++ b/etc/benchmarks/main.mjs
@@ -9,7 +9,7 @@ console.log();
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 await runner({
-  skip: false,
+  skip: true,
   name: 'deserialize({ oid, string }, { validation: { utf8: false } })',
   iterations,
   setup(libs) {
@@ -58,6 +58,46 @@ await runner({
   }
 });
 
+await runner({
+  skip: true,
+  name: 'Double Serialization',
+  iterations,
+  run(i, bson) {
+    bson.lib.serialize({ d: 2.3 });
+  }
+});
+
+await runner({
+  skip: false,
+  name: 'Double Deserialization',
+  iterations,
+  setup(libs) {
+    const bson = getCurrentLocalBSON(libs);
+    return bson.lib.serialize({ d: 2.3 });
+  },
+  run(i, bson, serialized_double) {
+    bson.lib.deserialize(serialized_double);
+  }
+});
+
+await runner({
+  skip: false,
+  name: 'Many Doubles Deserialization',
+  iterations,
+  setup(libs) {
+    const bson = getCurrentLocalBSON(libs);
+    let doubles = Object.fromEntries(
+      Array.from({ length: 1000 }, i => {
+        return [`a_${i}`, 2.3];
+      })
+    );
+    return bson.lib.serialize(doubles);
+  },
+  run(i, bson, serialized_doubles) {
+    bson.lib.deserialize(serialized_doubles);
+  }
+});
+
 // End
 console.log(
   'Total time taken to benchmark:',
diff --git a/src/float_parser.ts b/src/float_parser.ts
deleted file mode 100644
index c881f4cf..00000000
--- a/src/float_parser.ts
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2008, Fair Oaks Labs, Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  * Redistributions of source code must retain the above copyright notice,
-//    this list of conditions and the following disclaimer.
-//
-//  * Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-//  * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
-//    may be used to endorse or promote products derived from this software
-//    without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-//
-// Modifications to writeIEEE754 to support negative zeroes made by Brian White
-
-type NumericalSequence = { [index: number]: number };
-
-export function readIEEE754(
-  buffer: NumericalSequence,
-  offset: number,
-  endian: 'big' | 'little',
-  mLen: number,
-  nBytes: number
-): number {
-  let e: number;
-  let m: number;
-  const bBE = endian === 'big';
-  const eLen = nBytes * 8 - mLen - 1;
-  const eMax = (1 << eLen) - 1;
-  const eBias = eMax >> 1;
-  let nBits = -7;
-  let i = bBE ? 0 : nBytes - 1;
-  const d = bBE ? 1 : -1;
-  let s = buffer[offset + i];
-
-  i += d;
-
-  e = s & ((1 << -nBits) - 1);
-  s >>= -nBits;
-  nBits += eLen;
-  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
-
-  m = e & ((1 << -nBits) - 1);
-  e >>= -nBits;
-  nBits += mLen;
-  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
-
-  if (e === 0) {
-    e = 1 - eBias;
-  } else if (e === eMax) {
-    return m ? NaN : (s ? -1 : 1) * Infinity;
-  } else {
-    m = m + Math.pow(2, mLen);
-    e = e - eBias;
-  }
-  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
-}
-
-export function writeIEEE754(
-  buffer: NumericalSequence,
-  value: number,
-  offset: number,
-  endian: 'big' | 'little',
-  mLen: number,
-  nBytes: number
-): void {
-  let e: number;
-  let m: number;
-  let c: number;
-  const bBE = endian === 'big';
-  let eLen = nBytes * 8 - mLen - 1;
-  const eMax = (1 << eLen) - 1;
-  const eBias = eMax >> 1;
-  const rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
-  let i = bBE ? nBytes - 1 : 0;
-  const d = bBE ? -1 : 1;
-  const s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
-
-  value = Math.abs(value);
-
-  if (isNaN(value) || value === Infinity) {
-    m = isNaN(value) ? 1 : 0;
-    e = eMax;
-  } else {
-    e = Math.floor(Math.log(value) / Math.LN2);
-    if (value * (c = Math.pow(2, -e)) < 1) {
-      e--;
-      c *= 2;
-    }
-    if (e + eBias >= 1) {
-      value += rt / c;
-    } else {
-      value += rt * Math.pow(2, 1 - eBias);
-    }
-    if (value * c >= 2) {
-      e++;
-      c /= 2;
-    }
-
-    if (e + eBias >= eMax) {
-      m = 0;
-      e = eMax;
-    } else if (e + eBias >= 1) {
-      m = (value * c - 1) * Math.pow(2, mLen);
-      e = e + eBias;
-    } else {
-      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
-      e = 0;
-    }
-  }
-
-  if (isNaN(value)) m = 0;
-
-  while (mLen >= 8) {
-    buffer[offset + i] = m & 0xff;
-    i += d;
-    m /= 256;
-    mLen -= 8;
-  }
-
-  e = (e << mLen) | m;
-
-  if (isNaN(value)) e += 8;
-
-  eLen += mLen;
-
-  while (eLen > 0) {
-    buffer[offset + i] = e & 0xff;
-    i += d;
-    e /= 256;
-    eLen -= 8;
-  }
-
-  buffer[offset + i - d] |= s * 128;
-}
diff --git a/src/parser/deserializer.ts b/src/parser/deserializer.ts
index 6f3d567c..bd306c95 100644
--- a/src/parser/deserializer.ts
+++ b/src/parser/deserializer.ts
@@ -197,6 +197,7 @@ function deserializeObject(
   let isPossibleDBRef = isArray ? false : null;
 
   // While we have more left data left keep parsing
+  const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
   while (!done) {
     // Read the type
     const elementType = buffer[index++];
@@ -263,10 +264,10 @@ function deserializeObject(
         (buffer[index++] << 16) |
         (buffer[index++] << 24);
     } else if (elementType === constants.BSON_DATA_NUMBER && promoteValues === false) {
-      value = new Double(buffer.readDoubleLE(index));
+      value = new Double(dataview.getFloat64(index, true));
       index = index + 8;
     } else if (elementType === constants.BSON_DATA_NUMBER) {
-      value = buffer.readDoubleLE(index);
+      value = dataview.getFloat64(index, true);
       index = index + 8;
     } else if (elementType === constants.BSON_DATA_DATE) {
       const lowBits =
diff --git a/src/parser/serializer.ts b/src/parser/serializer.ts
index 1fa810ec..e76402aa 100644
--- a/src/parser/serializer.ts
+++ b/src/parser/serializer.ts
@@ -9,7 +9,6 @@ import type { Double } from '../double';
 import { ensureBuffer } from '../ensure_buffer';
 import { BSONError, BSONTypeError } from '../error';
 import { isBSONType } from '../extended_json';
-import { writeIEEE754 } from '../float_parser';
 import type { Int32 } from '../int_32';
 import { Long } from '../long';
 import { Map } from '../map';
@@ -79,6 +78,12 @@ function serializeString(
   return index;
 }
 
+const SPACE_FOR_FLOAT64 = new Uint8Array(8);
+const DV_FOR_FLOAT64 = new DataView(
+  SPACE_FOR_FLOAT64.buffer,
+  SPACE_FOR_FLOAT64.byteOffset,
+  SPACE_FOR_FLOAT64.byteLength
+);
 function serializeNumber(
   buffer: Buffer,
   key: string,
@@ -119,7 +124,8 @@ function serializeNumber(
     index = index + numberOfWrittenBytes;
     buffer[index++] = 0;
     // Write float
-    writeIEEE754(buffer, value, index, 'little', 52, 8);
+    DV_FOR_FLOAT64.setFloat64(0, value, true);
+    buffer.set(SPACE_FOR_FLOAT64, index);
     // Adjust index
     index = index + 8;
   }
@@ -487,7 +493,8 @@ function serializeDouble(
   buffer[index++] = 0;
 
   // Write float
-  writeIEEE754(buffer, value.value, index, 'little', 52, 8);
+  DV_FOR_FLOAT64.setFloat64(0, value.value, true);
+  buffer.set(SPACE_FOR_FLOAT64, index);
 
   // Adjust index
   index = index + 8;
diff --git a/test/node/bson_corpus.spec.test.js b/test/node/bson_corpus.spec.test.js
index b40d6c03..62dbf94b 100644
--- a/test/node/bson_corpus.spec.test.js
+++ b/test/node/bson_corpus.spec.test.js
@@ -121,11 +121,6 @@ describe('BSON Corpus', function () {
         describe('valid-bson', function () {
           for (const v of valid) {
             it(v.description, function () {
-              if (v.description === 'NaN with payload') {
-                // TODO(NODE-3630): remove custom float parser so we can handle the NaN payload data
-                this.skip();
-              }
-
               if (
                 v.description === 'All BSON types' &&
                 scenario._filename === 'multi-type-deprecated'
diff --git a/test/node/double_tests.js b/test/node/double_tests.js
index 9c690174..5346f6cf 100644
--- a/test/node/double_tests.js
+++ b/test/node/double_tests.js
@@ -3,36 +3,90 @@
 const BSON = require('../register-bson');
 const Double = BSON.Double;
 
-describe('Double', function () {
-  describe('Constructor', function () {
-    var value = 42.3456;
+describe('BSON Double Precision', function () {
+  context('class Double', function () {
+    describe('constructor()', function () {
+      const value = 42.3456;
 
-    it('Primitive number', function (done) {
-      expect(new Double(value).valueOf()).to.equal(value);
-      done();
+      it('Primitive number', function () {
+        expect(new Double(value).valueOf()).to.equal(value);
+      });
+
+      it('Number object', function () {
+        expect(new Double(new Number(value)).valueOf()).to.equal(value);
+      });
     });
 
-    it('Number object', function (done) {
-      expect(new Double(new Number(value)).valueOf()).to.equal(value);
-      done();
+    describe('#toString()', () => {
+      it('should serialize to a string', () => {
+        const testNumber = Math.random() * Number.MAX_VALUE;
+        const double = new Double(testNumber);
+        expect(double.toString()).to.equal(testNumber.toString());
+      });
+
+      const testRadices = [2, 8, 10, 16, 22];
+
+      for (const radix of testRadices) {
+        it(`should support radix argument: ${radix}`, () => {
+          const testNumber = Math.random() * Number.MAX_VALUE;
+          const double = new Double(testNumber);
+          expect(double.toString(radix)).to.equal(testNumber.toString(radix));
+        });
+      }
     });
   });
 
-  describe('toString', () => {
-    it('should serialize to a string', () => {
-      const testNumber = Math.random() * Number.MAX_VALUE;
-      const double = new Double(testNumber);
-      expect(double.toString()).to.equal(testNumber.toString());
+  function serializeThenDeserialize(value) {
+    const serializedDouble = BSON.serialize({ d: value });
+    const deserializedDouble = BSON.deserialize(serializedDouble, { promoteValues: false });
+    return deserializedDouble.d;
+  }
+
+  const testCases = [
+    { name: 'Infinity', doubleVal: new Double(Infinity), testVal: Infinity },
+    { name: '-Infinity', doubleVal: new Double(-Infinity), testVal: -Infinity },
+    { name: 'Number.EPSILON', doubleVal: new Double(Number.EPSILON), testVal: Number.EPSILON },
+    { name: 'Zero', doubleVal: new Double(0), testVal: 0 },
+    { name: 'Negative Zero', doubleVal: new Double(-0), testVal: -0 },
+    { name: 'NaN', doubleVal: new Double(NaN), testVal: NaN }
+  ];
+
+  for (const { name, doubleVal, testVal } of testCases) {
+    it(`should preserve the input value ${name} in Double serialize-deserialize roundtrip`, () => {
+      const roundTrippedVal = serializeThenDeserialize(doubleVal);
+      expect(Object.is(doubleVal.value, testVal)).to.be.true;
+      expect(Object.is(roundTrippedVal.value, doubleVal.value)).to.be.true;
     });
+  }
 
-    const testRadices = [2, 8, 10, 16, 22];
+  context('NaN with Payload', function () {
+    const NanPayloadBuffer = Buffer.from('120000000000F87F', 'hex');
+    const NanPayloadDV = new DataView(
+      NanPayloadBuffer.buffer,
+      NanPayloadBuffer.byteOffset,
+      NanPayloadBuffer.byteLength
+    );
+    const NanPayloadDouble = NanPayloadDV.getFloat64(0, true);
+    // Using promoteValues: false (returning raw BSON) in order to be able to check that payload remains intact
+    const serializedNanPayloadDouble = BSON.serialize({ d: NanPayloadDouble });
 
-    for (const radix of testRadices) {
-      it(`should support radix argument: ${radix}`, () => {
-        const testNumber = Math.random() * Number.MAX_VALUE;
-        const double = new Double(testNumber);
-        expect(double.toString(radix)).to.equal(testNumber.toString(radix));
-      });
-    }
+    it('should keep payload in serialize-deserialize roundtrip', function () {
+      expect(serializedNanPayloadDouble.subarray(7, 15)).to.deep.equal(NanPayloadBuffer);
+    });
+
+    it('should preserve NaN value in serialize-deserialize roundtrip', function () {
+      const { d: newVal } = BSON.deserialize(serializedNanPayloadDouble, { promoteValues: true });
+      expect(newVal).to.be.NaN;
+    });
+  });
+
+  it('NODE-4335: does not preserve -0 in serialize-deserialize roundtrip if JS number is used', function () {
+    // TODO (NODE-4335): -0 should be serialized as double
+    // This test is demonstrating the behavior of -0 being serialized as an int32 something we do NOT want to unintentionally change, but may want to change in the future, which the above ticket serves to track.
+    const value = -0;
+    const serializedDouble = BSON.serialize({ d: value });
+    const type = serializedDouble[4];
+    expect(type).to.not.equal(BSON.BSON_DATA_NUMBER);
+    expect(type).to.equal(BSON.BSON_DATA_INT);
   });
 });