Skip to content

suggestion: don't use bare floating point for math operations #2342

Open
@cwillisf

Description

@cwillisf

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions