1

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

5
  • 1
    One way would be to use new Float32Array([yourNumber])[0], but it’s not supported in all browsers. Why do you need the lost precision? Commented Aug 4, 2016 at 21:34
  • 2
    What do you need a "float" for? Context will help us understand what you are going for Commented Aug 4, 2016 at 21:40
  • I need to depict c style floating point numbers Commented Aug 4, 2016 at 21:41
  • For what? JS doesn't have C-style floats. Are you interfacing with C code? Commented Aug 4, 2016 at 21:44
  • What function/library are you trying to call, and using what means? REST API? Commented Aug 4, 2016 at 22:24

3 Answers 3

5

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 32 bits of information. I added a fallback for the case that Float32Array is not available:

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

    if ( d === 0 )
        return d;

    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, round, result;

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

    if ( exponent < -126 )
        return 0;
    if ( exponent > 127 )
        return sign*Infinity;

    return result;
}
Sign up to request clarification or add additional context in comments.

3 Comments

this gives pretty bad precision
@asehgal Yeah, isn’t that exactly what you wanted?
I didnt want BAD precision. I said a 32 bit representation is desired even if it comes with precision loss.
2

Another way is:

var doubleValue = Math.random()
var floatValue = ((doubleValue * 1e7) | 0) / 1e7

Comments

1

Just use Math.fround() - it returns the nearest 32-bit single precision float representation of a number.

Math.fround() - JavaScript | MDN

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.