-
Ok, so summarised the
correct.js
andincorrect.js
output the same in browser. Tested in node, they do output the same:> node .\correct.js L145 msband=E40000 L146 midand=C000 L147 lsband=0 > node .\incorrect.js L145 msband=E40000 L146 midand=C000 L147 lsband=0
, but different in Espruino, right?
My guess is rounding is somewhat messed up, the interesting part:
>var val = 915E6; =915000000 >var newVal = val * Math.pow(2, 19); =479723519999999.9375 >var newDiv = newVal / 32000000 =14991360 // but doesn't equal to the literal value: >newDiv==(14991360) =false // it's smaller: >newDiv<(14991360) =true >newDiv>(14991360) =false
So it's not exactly 14991360, but a bit smaller. In your
correct
version you set it to the exact literal value, that's why it behaves differently.// Espruino: >newDiv & 0xff00 =48896 // with literal value >14991360 & 0xff00 =49152
If you round it, you get what you expect:
>Math.round(newDiv) == 14991360 =true >Math.round(newDiv) & 0xff00 =49152 // in hex: >(newDiv & 0xff00).toString(16) ="bf00" >(Math.round(newDiv) & 0xff00).toString(16) ="c000"
That doesn't mean I have an explanation, probably a different behaviour with bitwise operations on fractions in Espruino.
Maybe a bug? Because after explicit rounding it works the same as in node / browser.
Thr 2019.07.25
This is a rather strange anomally, and not what was originally tackled.
Foundation:
Was in the process of converting this C++ script into Javascript:
C/C++ uses a long int 64 bits, so shifting 19 places will work, and it appears that the uint8_t typecast is being used to strip leading and trailing bytes.
Kept getting incorrect result. Had a hunch that left shifing 19 places might be an issue
Down a rabbit hole, . . . but the wrong one!
After manually creating binary strings
0001101101000100111001010110000000000000000000000000 / 0001111010000100100000000000
determined that the bits were getting sent to no mans land during left shift, as expected.
Verified how Javascript vars work:
"The MAX_SAFE_INTEGER constant has a value of 9007199254740991 (9,007,199,254,740,991 or ~9 quadrillion). The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between -(253 - 1) and 253 - 1."
"They are 64-bit floating point values, the largest exact integral value is 253-1, or 9007199254740991 . In ES6, this is defined as Number.MAX_SAFE_INTEGER. Note that the bitwise operators and shift operators operate on 32-bit ints, so in that case, the max safe integer is 231-1, or 2147483647."
So the data should fit inside that value, as we are one third of the max value. Realized that as left shifting is nothing more than doubling, tried the same using
Math.pow()
Find that rabbit hole.
Process:
Wrote many string representation formatting functions to show the decimal values shown using the WebIDE debugger as both formatted hex and formatted binary to determine if it was in fact a shift issue.
It didn't appear to be, . . . until . . .
Spent two days attempting to understand why a previously working/tested format function all of a sudden started giving incorrect output. In a final act of desperation, started whacking out everything that wasn't needed from the 700+ lines of code. Still had the incorrect output.
Decided to make Html scripting pages to test. They tested fine. So where was the issue?
Found the rabbit hole.
Observation:
I made a copy of the original data in a new var assignment. An Viola! Found what was causing what appeared to be a bit shift issue. Still not quite sure, as the debugger doesn't reveal anything new on the right-hand editor side of the WebIDE. But it appears to be the assignment of an existing var!
The offending lines. They appear to be valid to me. See comment at top of source file for commented out lines. Files contain identical source, just more comments in 'incorrect' version.
Google's closure compiler shows zero errors
And with the two lines commented in:
Hoisting doesn't appear to be an issue, nor does redefining:
"If you re-declare a JavaScript variable, it will not lose its value."
Works in Chrome, either .htm files demonstrate this.
Spending as much time on this as I have, I would really like to understand where in the source this culprit exists. I'll try a few attempts at renaming the var declaration and assignment, to see if that may be part of the issue.
The two lines commented out are indicated in each source file at page top.