Math.pow ?

Posted on
  • Hi Gordon,

    It was not easy to isolate the following problem:

    The Code:

    a=16;
    b=16;
    console.log('A:'+a);
    console.log('B:'+b);
    console.log('AND Result1:'+(a&b));

    a=16;
    b=Math.pow(2,4); // Also 16
    console.log('A:'+a);
    console.log('B:'+b);
    console.log('AND Result2:'+(a&b));

    Espruino Output:

    1v63 Copyright 2014 G.Williams

    echo(0);
    A:16
    B:16
    AND Result1:16
    A:16
    B:16
    AND Result2:0
    =undefined

    On jsoncole.com, the output is the following. See "AND Result2", should be 16 too.

    A:16
    B:16
    AND Result1:16
    A:16
    B:16
    AND Result2:16

    See http://jsconsole.com/?a%3D16%3B%0Ab%3D16­%3B%0Aconsole.log(%27A%3A%27%2Ba)%3B%0Ac­onsole.log(%27B%3A%27%2Bb)%3B%0Aconsole.­log(%27AND%20Result1%3A%27%2B(a%26b))%3B­%0A%0Aa%3D16%3B%0Ab%3DMath.pow(2%2C4)%3B­%0Aconsole.log(%27A%3A%27%2Ba)%3B%0Acons­ole.log(%27B%3A%27%2Bb)%3B%0Aconsole.log­(%27AND%20Result2%3A%27%2B(a%26b))%3B

    Thanks

    Sacha

  • Much shorter_

    16&Math.pow(2,4);

    should return 16 not 0.

    Sacha

  • Hmm. This returns correctly 16:

    16&(Math.pow(2,4)+1-1);

    This incorrectly 15:

    parseInt(Math.pow(2,4));

    Sacha

  • This returns correctly 16:

    Number(Math.pow(2,4));

    But this not 16, it returns 0:

    16&Number(Math.pow(2,4));

    Sacha

  • Argh. It's just floating point inaccuracy. While I think Math.pow isn't as accurate as it could be, floating point maths will always cause problems like this. In this case jsconsole is right and Espruino gets it wrong, but I bet if you looked hard enough you could find similar cases where it did something strange too.

    If you do some floating point operation it probably won't be entirely accurate, and it's 50/50 whether it'll be above the correct number or below it. If you drop the fractional bits, even if the number was 15.99999999999 you'll still just get 15.

    For now, if you just do 16&Math.round(Math.pow(2,4)) it'll fix it.

    I could add some code that was a bit like: if (is_not_fractional(a) && is_not_fractional(b) && b>0) return round(Math.pow(a,b)); but it's a bit of a hack and I wonder whether it'll cause problems later.

  • Just to add, the issue is the conversion to integer, so just adding 0| is enough to test what happens.

  • Thx Gordon.

  • Hey,

    I realiced that "Math.pow(2,4)" can be replaced with "1<<4". Much better ;-)

    Sacha

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Math.pow ?

Posted by Avatar for Sacha @Sacha

Actions