asehgal - 1 year ago 208
Javascript Question

# From double to float in JavaScript?

My understanding is that all numbers in JavaScript are double-precision floating-point. How can I convert a double to a float in JavaScript? I understand the precision loss, but that is tolerable.

I need to depict C style floating point numbers

This will work in modern engines:

``````function doubleToFloat ( d ) {
if ( Float32Array )
return new Float32Array([d])[0];
}
``````

Note that the data type of the result is still number (double precision), but it only uses the bits that a single-precision float would also have.

EDIT:

I added an incomplete! fallback for the case that Float32Array is not available:

``````function doubleToFloat ( d ) {
if ( Float32Array )
return new Float32Array([d])[0];

var sign = 2*(d >= 0) - 1;
var b = Math.abs( d ).toString( 2 );
var decimalIndex = b.indexOf( '.' );
var oneIndex = b.indexOf( '1' );
var exponent, mantissa, result;

if( decimalIndex === -1 ) {
exponent = b.length - 1;
mantissa = b.substr( 0, 23 );
result = sign*parseInt( mantissa, 2 )*Math.pow( 2, 1 + exponent - mantissa.length );
} else if ( decimalIndex === 1 ) {
exponent = 1 - oneIndex;
if ( oneIndex === 0 ) {
mantissa = '1' + b.substr( 2, 23 );
result = sign*parseInt( mantissa, 2 )*Math.pow( 2, 1 - mantissa.length );
} else {
mantissa = b.substr( oneIndex, 23 );
result = sign*parseInt( mantissa, 2 )*Math.pow( 2, 1 + exponent - mantissa.length );
}
} else {
exponent = decimalIndex - 1;
mantissa = b.replace( '.', '' ).substr( 0, 23 );
result = sign*parseInt( mantissa, 2 )*Math.pow( 2, decimalIndex - mantissa.length );
}

if ( exponent < -127 || exponent > 128 )
throw new RangeError( 'Double ' + d + ' outside single-precision range' );

return result;
}
``````

It seems to work pretty well, but it is not perfect. I have not tested it on many inputs, and I have made no attempt at rounding correctly.

Tests:

``````const RealFloat32Array = Float32Array;
Float32Array = false;

const tests = [
-5, 0, 1, 1.01, 0.125, 0.00009,
1.0000000001,
10000.12312421321,
500000000.001,
5000000000.001,
50000000000.001,
3.402823e+38
];

function test ( d ) {

const usingFloat32 = new RealFloat32Array([d])[0]
const usingAlgorithm = doubleToFloat( d );

if ( usingFloat32 !== usingAlgorithm )
console.error( 'Test FAILED: ', { d, usingFloat32, usingAlgorithm } );

}

tests.forEach( test );
``````

Result (9 passes, 3 fails):

``````Test FAILED:  Object {d: 0.00009, usingFloat32: 0.00009000000136438757, usingAlgorithm: 0.00008999998681247234}
Test FAILED:  Object {d: 50000000000.001, usingFloat32: 49999998976, usingAlgorithm: 49999994880}
Test FAILED:  Object {d: 3.402823e+38, usingFloat32: 3.4028230607370965e+38, usingAlgorithm: 3.4028228579130005e+38}
``````

Those are probably all caused by the fact that I don't do any rounding.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download