Topic
  • 7 replies
  • Latest Post - ‏2012-11-28T16:53:06Z by SystemAdmin
SystemAdmin
SystemAdmin
7615 Posts

Pinned topic Javascript precision for doubles

‏2012-11-22T13:12:25Z |
I hit this problem today:
http://stackoverflow.com/questions/1458633/elegant-workaround-for-javascript-floating-point-number-problem
The moral is - any time we do operations with decimals we have to round. Quite annoying I agree...
Our approach is: Math.round( (X - Y) * 100) / 100
However, I heard horror stories that even when we type value in a coach input field like 0.1 , it gets represented as 0.09999999995 in the underlying bound variable. Have you noticed this and how do you work around this?
Updated on 2012-11-28T16:53:06Z at 2012-11-28T16:53:06Z by SystemAdmin
  • kolban
    kolban
    3316 Posts

    Re: Javascript precision for doubles

    ‏2012-11-22T16:57:20Z  
    I noticed this a while back. I was astonished at the apparent representation of floating point in JavaScript. I don't know the technical reasons under the covers but when 1/10 0.1 I start getting very concerned. I'd have a google across the internet and see what we find. It is possible that the IBM BPM data type "Decimal" is not represented as a JavaScript "Number" but is instead implemented under the covers as a "Java" double.

    Do you have an example/test that shows a problem?

    Neil
  • SystemAdmin
    SystemAdmin
    7615 Posts

    Re: Javascript precision for doubles

    ‏2012-11-22T17:10:04Z  
    • kolban
    • ‏2012-11-22T16:57:20Z
    I noticed this a while back. I was astonished at the apparent representation of floating point in JavaScript. I don't know the technical reasons under the covers but when 1/10 0.1 I start getting very concerned. I'd have a google across the internet and see what we find. It is possible that the IBM BPM data type "Decimal" is not represented as a JavaScript "Number" but is instead implemented under the covers as a "Java" double.

    Do you have an example/test that shows a problem?

    Neil
    
    var x = 0.01; var y = 0.01;   log.info(
    "start----"); 
    
    for (var i = 0 ; i < 100; i++)
    { x = x + 0.01; var string = x + 
    "";   
    
    if( string.length > 4 )
    { log.info(
    "X: " + x); 
    } 
    } log.info(
    "End----");
    
  • SystemAdmin
    SystemAdmin
    7615 Posts

    Re: Javascript precision for doubles

    ‏2012-11-28T03:04:37Z  
    <pre class="jive-pre"> var x = 0.01; var y = 0.01; log.info( "start----"); for (var i = 0 ; i < 100; i++) { x = x + 0.01; var string = x + ""; if( string.length > 4 ) { log.info( "X: " + x); } } log.info( "End----"); </pre>
    All of this also gets into some areas that are likely to cause very odd behavior over all. If you declare a variable with the "var" construct then it is (generally) javascript. JS is weird as it is losely typed so if I say
    
    var myInt = 
    "One"; var myString = 
    "1";
    


    The myInt variable will be a JS string, but the myString variable will be a JS Number. However if I am using teamworks variables, then they wind up being backed (as Neil notes) by Java constructs. However they get there through the JS engine so weirdness happens. If I change my above example to use teamworks variable tw.local.myInt of type Integer and tw.local.myString of type string, I'm fairly certain the following will work -

    
    tw.local.myString = 
    "1"; tw.local.myInt = tw.local.myString
    


    Allowing an implicit conversion where I do not believe Java would allow one to take place. Note that if you neglect the quotes on the first line I have in the past seen that cause a type cast error.

    If I have time I'll take the example below and run it with JS, and Decimal types and see if the results are different.

    Andrew Paier | Director of Special Operations | BP3 Global, Inc. www.bp-3.com
  • SystemAdmin
    SystemAdmin
    7615 Posts

    Re: Javascript precision for doubles

    ‏2012-11-28T09:13:30Z  
    All of this also gets into some areas that are likely to cause very odd behavior over all. If you declare a variable with the "var" construct then it is (generally) javascript. JS is weird as it is losely typed so if I say
    <pre class="jive-pre"> var myInt = "One"; var myString = "1"; </pre>

    The myInt variable will be a JS string, but the myString variable will be a JS Number. However if I am using teamworks variables, then they wind up being backed (as Neil notes) by Java constructs. However they get there through the JS engine so weirdness happens. If I change my above example to use teamworks variable tw.local.myInt of type Integer and tw.local.myString of type string, I'm fairly certain the following will work -

    <pre class="jive-pre"> tw.local.myString = "1"; tw.local.myInt = tw.local.myString </pre>

    Allowing an implicit conversion where I do not believe Java would allow one to take place. Note that if you neglect the quotes on the first line I have in the past seen that cause a type cast error.

    If I have time I'll take the example below and run it with JS, and Decimal types and see if the results are different.

    Andrew Paier | Director of Special Operations | BP3 Global, Inc. www.bp-3.com
    Any Javascript variables suffer from the problem described above.
    It is outrageous really - BPM does not support basic arithmetic operations...
    How could someone decide that having Javascript on the serverside is a good idea?
  • SystemAdmin
    SystemAdmin
    7615 Posts

    Re: Javascript precision for doubles

    ‏2012-11-28T15:27:00Z  
    Any Javascript variables suffer from the problem described above.
    It is outrageous really - BPM does not support basic arithmetic operations...
    How could someone decide that having Javascript on the serverside is a good idea?
    One must always strike a balance. The underlying technology of IBM BPM for these items has been around since 2003, which was when that technology decision was made. The underlying goal seems to have been to avoid the "code, compile, deploy, repeat" development pattern at the time. Use of server side JS allowed for that functionality to work. The ability to execute code that was saved in a central database was a very unique concept at the time.

    The nature of binary numbers is such that all decimal representations that are backed by pure binaries will have floating point errors. The question is simpy how bad those errors are and how much you can control them. Last time I tried, in both java and C++ the formula -
    
    
    
    double x = (1/3)*3;
    

    Did not evaluate to an answer of 1. Based on your assessment, I could then state that Java does not support basic arithmetic functions from that use case.

    There are of course Java and C libraries that are designed to deal with this limitation, but it comes at a cost of significantly higher computing costs for standard arithmetic functions. So far I've never needed to use them in a BPM system since any complex math being done was done on an heritage system that had already decided how to deal with these errors.

    If this is causing you signficant pain you can create Java methods to do your mathmatic functions and return the values to BPM as a string value, which would eliminate the JS in accuracy you are seeing. I'm sure there are also other options in Advanced using the Integraiton Designer that I am not yet familiar with.

    Andrew Paier | Director of Special Operations | BP3 Global, Inc. www.bp-3.com
  • SystemAdmin
    SystemAdmin
    7615 Posts

    Re: Javascript precision for doubles

    ‏2012-11-28T15:44:49Z  
    One must always strike a balance. The underlying technology of IBM BPM for these items has been around since 2003, which was when that technology decision was made. The underlying goal seems to have been to avoid the "code, compile, deploy, repeat" development pattern at the time. Use of server side JS allowed for that functionality to work. The ability to execute code that was saved in a central database was a very unique concept at the time.

    The nature of binary numbers is such that all decimal representations that are backed by pure binaries will have floating point errors. The question is simpy how bad those errors are and how much you can control them. Last time I tried, in both java and C++ the formula -
    <pre class="jive-pre"> double x = (1/3)*3; </pre>
    Did not evaluate to an answer of 1. Based on your assessment, I could then state that Java does not support basic arithmetic functions from that use case.

    There are of course Java and C libraries that are designed to deal with this limitation, but it comes at a cost of significantly higher computing costs for standard arithmetic functions. So far I've never needed to use them in a BPM system since any complex math being done was done on an heritage system that had already decided how to deal with these errors.

    If this is causing you signficant pain you can create Java methods to do your mathmatic functions and return the values to BPM as a string value, which would eliminate the JS in accuracy you are seeing. I'm sure there are also other options in Advanced using the Integraiton Designer that I am not yet familiar with.

    Andrew Paier | Director of Special Operations | BP3 Global, Inc. www.bp-3.com
    0.1 + 0.2 must always be 0.3, at least I expect it.

    "Advanced" being Java based would calculate this correctly, but I would not recommend it to our clients "Advanced" just because "Standard" cannot do the maths.

    Have you observed any problems during the binding of the variables or only during math operations? Should we really try not to have decimals at all for data types? Or have decimals but never do simple maths with them - use only Javascrip wrapping operations.
  • SystemAdmin
    SystemAdmin
    7615 Posts

    Re: Javascript precision for doubles

    ‏2012-11-28T16:53:06Z  
    0.1 + 0.2 must always be 0.3, at least I expect it.

    "Advanced" being Java based would calculate this correctly, but I would not recommend it to our clients "Advanced" just because "Standard" cannot do the maths.

    Have you observed any problems during the binding of the variables or only during math operations? Should we really try not to have decimals at all for data types? Or have decimals but never do simple maths with them - use only Javascrip wrapping operations.
    You don't have to have Advanced to access java. You can leverage code in java jar files via the integration services in standard. You can also get to it using LiveConnect in JS, but that tends to be frowned upon.

    Also, your expectations do not reflect reality. I just ran the following -

    
    
    
    public 
    
    class QuickMathCheck
    { 
    
    public 
    
    static 
    
    void main(String[] args)
    { 
    
    double myDouble = 0.2+0.1; 
    
    float myFloat = 0.2f+0.1f; System.out.println(
    "Float is "+myFloat+
    " Double is "+myDouble); 
    } 
    }
    


    The value for double in that example winds up being the same as I get doing the same math in JS and using tw.object.Double which is - 0.30000000000000004. So again, if you say Java does this correctly then so does JS. If you say the JS result is wrong, so is the java result.

    Interestingly the float actually returned 0.3 even though without the "f" notation I was told I would lose percision. I guess in this case being less precise is good….

    Andrew Paier | Director of Special Operations | BP3 Global, Inc. www.bp-3.com