Scratch-vm: suggestion: don't use bare floating point for math operations

Created on 25 Mar 2020  路  4Comments  路  Source: LLK/scratch-vm

Expected Behavior

Clicking on a + block with 0.1 and 0.2 as its arguments should show 0.3 as the result.

Actual Behavior

Clicking on a + block with 0.1 and 0.2 as its arguments shows 0.30000000000000004 as the result.

Example:
image

Similar results can be seen with asin of 0.5 and other mathematical expressions.

Suggestion

For background information, see: https://0.30000000000000004.com/

One could argue that, since 0.1 and 0.2 cannot be accurately represented in IEEE floating point numbers, it's "correct" to show 0.30000000000000004 as the answer when adding those two values. I would argue that doing so is only valuable to a minority of our audience, and makes working with math more difficult for the majority of our audience.

In my opinion we should consider using something like https://github.com/MikeMcl/decimal.js for math blocks in Scratch so that the results of Scratch math expressions are correct without having to consider the details of IEEE floating point format. For example:

let a = Decimal('0.1');
let b = Decimal('0.2');
let c = a.add(b); // same as Decimal.add('0.1', '0.2')

console.log(c.toString()); // shows "0.3"
console.log(c == 0.3); // shows "true"
console.log(c === 0.3); // shows "false"
let a = Decimal('0.5');
let b = a.asin(); // same as Decimal.asin('0.5')

const pi = Decimal.acos(-1);
const radiansToDegrees = Decimal.div(180, pi);
let bDegrees = b.mul(radiansToDegrees);

console.log(bDegrees.toString()); // shows "30"
console.log(bDegrees == 30); // shows "true"
console.log(bDegrees === 30); // shows "false"

One downside is that math operations will be somewhat slower. If we do this, we should do at least two kinds of testing:

  1. Test several complex projects, especially math-driven ones, to see if performance suffers too much, and
  2. Check for compatibility problems since there may be projects out there relying on the floating-point behavior, for example with equality or inequality tests.
Medium Impact Medium Severity enhancement priority 3

All 4 comments

Right now, there's a lot of interpreter overhead in the VM, so I suspect math-heavy projects may not appear to be impacted. However, I'm concerned that under a more-optimized future version of this VM, or under current alternative VM implementations which want to remain Scratch-compatible, decimals could become a bottleneck.

Also, GC pressure could be an issue-- it looks like doing math with decimal.js requires creating a new object for every number in the calculation.

What if we change all the math to base 2

@fsih Support (if it's totally normal)

@apple502j Sorry, no can do

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jwzimmer picture jwzimmer  路  3Comments

LiFaytheGoblin picture LiFaytheGoblin  路  5Comments

thisandagain picture thisandagain  路  5Comments

ericrosenbaum picture ericrosenbaum  路  3Comments

CatsAreFluffy picture CatsAreFluffy  路  6Comments