Will someone ever be faced with wrong results of simple arithmetic operations on floating point numbers if...












0















Note: numbers which I'm talking about are currency, thus don't have more than two digits in fractional part.



I've tested 4 libraries (Decimal.js, Numeral.js, Big.js and Math.js) and a simple plain javascript implementation function (which uses Math.round for cutting off fractional part) with two arithmetic operations:




  • 0.55 * 100 => 55 // but it gives 55.00000000000001

  • 0.2 + 0.1 => 0.3 // but it gives 0.30000000000000004


Test script (node v10.4.1, Ubuntu 16.04LTS)



const { Decimal } = require('decimal.js')
const numeral = require('numeral')
const Big = require('big.js')
const math = require('mathjs')

const assert = require('assert')

function roundMultiply () {
return Math.round(0.55 * 100)
}

function roundAdd () {
return Math.round((0.2 + 0.1) * 100) / 100
}


function decimalMultiply () {
return new Decimal(0.55).mul(new Decimal(100))
}

function decimalAdd () {
return new Decimal(0.2).add(new Decimal(0.1))
}


function numeralMultiply () {
return numeral(0.55).multiply(100).value()
}

function numeralAdd () {
return numeral(0.2).add(0.1).value()
}


function bigJsMultiply () {
return +(new Big(0.55).times(100))
}

function bigJsAdd () {
return +(new Big(0.2).add(0.1))
}


function mathJsMultiply () {
return math.number(math.multiply(math.fraction(0.55), 100))
}

function mathJsAdd () {
return math.number(math.add(math.fraction(0.2), math.fraction(0.1)))
}

function test (fun, funName) {
console.time(funName)

for (let i = 0; i < 100000; i++) {
fun()
}

console.timeEnd(funName)
}

console.log('test multiplication results...')

assert(String(roundMultiply()) === '55')
assert(String(decimalMultiply()) === '55')
assert(String(numeralMultiply()) === '55')
assert(String(bigJsMultiply()) === '55')
assert(String(mathJsMultiply()) === '55')

console.log('test multiplication performance...')

test(roundMultiply, 'roundMultiply')
test(decimalMultiply, 'decimalMultiply')
test(numeralMultiply, 'withNumeral')
test(bigJsMultiply, 'withBigJs')
test(mathJsMultiply, 'mathJsMultiply')

console.log('test adding results...')

assert(String(roundAdd()) === '0.3')
assert(String(decimalAdd()) === '0.3')
assert(String(numeralAdd()) === '0.3')
assert(String(bigJsAdd()) === '0.3')
assert(String(mathJsAdd()) === '0.3')

console.log('test adding performance...')

test(roundAdd, 'roundAdd')
test(decimalAdd, 'decimalAdd')
test(numeralAdd, 'numeralAdd')
test(bigJsAdd, 'bigJsAdd')
test(mathJsAdd, 'mathJsAdd')


Results



roundMultiply: 2.673ms
withBigJs: 123.759ms
decimalMultiply: 172.068ms
withNumeral: 206.626ms
mathJsMultiply: 255.870ms

roundAdd: 2.317ms
mathJsAdd: 68.212ms
numeralAdd: 139.752ms
decimalAdd: 184.210ms
bigJsAdd: 222.685ms


As you can see, roundAdd and roundMultiply are far ahead of all other functions.



My main question: are there operands having at most two digits in fractional part and such, which, when peforming simple arithmetic operations (+, -, *, /) with them, whould give incorrect result when using Math.round? Because I can't see any reason why would I need to use any of those (or other libraries) taking into account their performance.










share|improve this question

























  • Possible duplicate of Is floating point math broken?

    – duffymo
    Nov 13 '18 at 15:04






  • 4





    @duffymo Come on, guys, this site becomes useless because each question is similar to some another question or contains similar keys in its subject or description. Do you really think that because that question is also about binary arithmetic inaccuracy there is no doubt that it contains answers will I ever be faced with errors because of Math.round usage instead of special JS library? Well, may be you think my question has not the best subject, in that case can you please suggest better one or what I should improve in it? Thanks

    – gumkins
    Nov 13 '18 at 18:54
















0















Note: numbers which I'm talking about are currency, thus don't have more than two digits in fractional part.



I've tested 4 libraries (Decimal.js, Numeral.js, Big.js and Math.js) and a simple plain javascript implementation function (which uses Math.round for cutting off fractional part) with two arithmetic operations:




  • 0.55 * 100 => 55 // but it gives 55.00000000000001

  • 0.2 + 0.1 => 0.3 // but it gives 0.30000000000000004


Test script (node v10.4.1, Ubuntu 16.04LTS)



const { Decimal } = require('decimal.js')
const numeral = require('numeral')
const Big = require('big.js')
const math = require('mathjs')

const assert = require('assert')

function roundMultiply () {
return Math.round(0.55 * 100)
}

function roundAdd () {
return Math.round((0.2 + 0.1) * 100) / 100
}


function decimalMultiply () {
return new Decimal(0.55).mul(new Decimal(100))
}

function decimalAdd () {
return new Decimal(0.2).add(new Decimal(0.1))
}


function numeralMultiply () {
return numeral(0.55).multiply(100).value()
}

function numeralAdd () {
return numeral(0.2).add(0.1).value()
}


function bigJsMultiply () {
return +(new Big(0.55).times(100))
}

function bigJsAdd () {
return +(new Big(0.2).add(0.1))
}


function mathJsMultiply () {
return math.number(math.multiply(math.fraction(0.55), 100))
}

function mathJsAdd () {
return math.number(math.add(math.fraction(0.2), math.fraction(0.1)))
}

function test (fun, funName) {
console.time(funName)

for (let i = 0; i < 100000; i++) {
fun()
}

console.timeEnd(funName)
}

console.log('test multiplication results...')

assert(String(roundMultiply()) === '55')
assert(String(decimalMultiply()) === '55')
assert(String(numeralMultiply()) === '55')
assert(String(bigJsMultiply()) === '55')
assert(String(mathJsMultiply()) === '55')

console.log('test multiplication performance...')

test(roundMultiply, 'roundMultiply')
test(decimalMultiply, 'decimalMultiply')
test(numeralMultiply, 'withNumeral')
test(bigJsMultiply, 'withBigJs')
test(mathJsMultiply, 'mathJsMultiply')

console.log('test adding results...')

assert(String(roundAdd()) === '0.3')
assert(String(decimalAdd()) === '0.3')
assert(String(numeralAdd()) === '0.3')
assert(String(bigJsAdd()) === '0.3')
assert(String(mathJsAdd()) === '0.3')

console.log('test adding performance...')

test(roundAdd, 'roundAdd')
test(decimalAdd, 'decimalAdd')
test(numeralAdd, 'numeralAdd')
test(bigJsAdd, 'bigJsAdd')
test(mathJsAdd, 'mathJsAdd')


Results



roundMultiply: 2.673ms
withBigJs: 123.759ms
decimalMultiply: 172.068ms
withNumeral: 206.626ms
mathJsMultiply: 255.870ms

roundAdd: 2.317ms
mathJsAdd: 68.212ms
numeralAdd: 139.752ms
decimalAdd: 184.210ms
bigJsAdd: 222.685ms


As you can see, roundAdd and roundMultiply are far ahead of all other functions.



My main question: are there operands having at most two digits in fractional part and such, which, when peforming simple arithmetic operations (+, -, *, /) with them, whould give incorrect result when using Math.round? Because I can't see any reason why would I need to use any of those (or other libraries) taking into account their performance.










share|improve this question

























  • Possible duplicate of Is floating point math broken?

    – duffymo
    Nov 13 '18 at 15:04






  • 4





    @duffymo Come on, guys, this site becomes useless because each question is similar to some another question or contains similar keys in its subject or description. Do you really think that because that question is also about binary arithmetic inaccuracy there is no doubt that it contains answers will I ever be faced with errors because of Math.round usage instead of special JS library? Well, may be you think my question has not the best subject, in that case can you please suggest better one or what I should improve in it? Thanks

    – gumkins
    Nov 13 '18 at 18:54














0












0








0








Note: numbers which I'm talking about are currency, thus don't have more than two digits in fractional part.



I've tested 4 libraries (Decimal.js, Numeral.js, Big.js and Math.js) and a simple plain javascript implementation function (which uses Math.round for cutting off fractional part) with two arithmetic operations:




  • 0.55 * 100 => 55 // but it gives 55.00000000000001

  • 0.2 + 0.1 => 0.3 // but it gives 0.30000000000000004


Test script (node v10.4.1, Ubuntu 16.04LTS)



const { Decimal } = require('decimal.js')
const numeral = require('numeral')
const Big = require('big.js')
const math = require('mathjs')

const assert = require('assert')

function roundMultiply () {
return Math.round(0.55 * 100)
}

function roundAdd () {
return Math.round((0.2 + 0.1) * 100) / 100
}


function decimalMultiply () {
return new Decimal(0.55).mul(new Decimal(100))
}

function decimalAdd () {
return new Decimal(0.2).add(new Decimal(0.1))
}


function numeralMultiply () {
return numeral(0.55).multiply(100).value()
}

function numeralAdd () {
return numeral(0.2).add(0.1).value()
}


function bigJsMultiply () {
return +(new Big(0.55).times(100))
}

function bigJsAdd () {
return +(new Big(0.2).add(0.1))
}


function mathJsMultiply () {
return math.number(math.multiply(math.fraction(0.55), 100))
}

function mathJsAdd () {
return math.number(math.add(math.fraction(0.2), math.fraction(0.1)))
}

function test (fun, funName) {
console.time(funName)

for (let i = 0; i < 100000; i++) {
fun()
}

console.timeEnd(funName)
}

console.log('test multiplication results...')

assert(String(roundMultiply()) === '55')
assert(String(decimalMultiply()) === '55')
assert(String(numeralMultiply()) === '55')
assert(String(bigJsMultiply()) === '55')
assert(String(mathJsMultiply()) === '55')

console.log('test multiplication performance...')

test(roundMultiply, 'roundMultiply')
test(decimalMultiply, 'decimalMultiply')
test(numeralMultiply, 'withNumeral')
test(bigJsMultiply, 'withBigJs')
test(mathJsMultiply, 'mathJsMultiply')

console.log('test adding results...')

assert(String(roundAdd()) === '0.3')
assert(String(decimalAdd()) === '0.3')
assert(String(numeralAdd()) === '0.3')
assert(String(bigJsAdd()) === '0.3')
assert(String(mathJsAdd()) === '0.3')

console.log('test adding performance...')

test(roundAdd, 'roundAdd')
test(decimalAdd, 'decimalAdd')
test(numeralAdd, 'numeralAdd')
test(bigJsAdd, 'bigJsAdd')
test(mathJsAdd, 'mathJsAdd')


Results



roundMultiply: 2.673ms
withBigJs: 123.759ms
decimalMultiply: 172.068ms
withNumeral: 206.626ms
mathJsMultiply: 255.870ms

roundAdd: 2.317ms
mathJsAdd: 68.212ms
numeralAdd: 139.752ms
decimalAdd: 184.210ms
bigJsAdd: 222.685ms


As you can see, roundAdd and roundMultiply are far ahead of all other functions.



My main question: are there operands having at most two digits in fractional part and such, which, when peforming simple arithmetic operations (+, -, *, /) with them, whould give incorrect result when using Math.round? Because I can't see any reason why would I need to use any of those (or other libraries) taking into account their performance.










share|improve this question
















Note: numbers which I'm talking about are currency, thus don't have more than two digits in fractional part.



I've tested 4 libraries (Decimal.js, Numeral.js, Big.js and Math.js) and a simple plain javascript implementation function (which uses Math.round for cutting off fractional part) with two arithmetic operations:




  • 0.55 * 100 => 55 // but it gives 55.00000000000001

  • 0.2 + 0.1 => 0.3 // but it gives 0.30000000000000004


Test script (node v10.4.1, Ubuntu 16.04LTS)



const { Decimal } = require('decimal.js')
const numeral = require('numeral')
const Big = require('big.js')
const math = require('mathjs')

const assert = require('assert')

function roundMultiply () {
return Math.round(0.55 * 100)
}

function roundAdd () {
return Math.round((0.2 + 0.1) * 100) / 100
}


function decimalMultiply () {
return new Decimal(0.55).mul(new Decimal(100))
}

function decimalAdd () {
return new Decimal(0.2).add(new Decimal(0.1))
}


function numeralMultiply () {
return numeral(0.55).multiply(100).value()
}

function numeralAdd () {
return numeral(0.2).add(0.1).value()
}


function bigJsMultiply () {
return +(new Big(0.55).times(100))
}

function bigJsAdd () {
return +(new Big(0.2).add(0.1))
}


function mathJsMultiply () {
return math.number(math.multiply(math.fraction(0.55), 100))
}

function mathJsAdd () {
return math.number(math.add(math.fraction(0.2), math.fraction(0.1)))
}

function test (fun, funName) {
console.time(funName)

for (let i = 0; i < 100000; i++) {
fun()
}

console.timeEnd(funName)
}

console.log('test multiplication results...')

assert(String(roundMultiply()) === '55')
assert(String(decimalMultiply()) === '55')
assert(String(numeralMultiply()) === '55')
assert(String(bigJsMultiply()) === '55')
assert(String(mathJsMultiply()) === '55')

console.log('test multiplication performance...')

test(roundMultiply, 'roundMultiply')
test(decimalMultiply, 'decimalMultiply')
test(numeralMultiply, 'withNumeral')
test(bigJsMultiply, 'withBigJs')
test(mathJsMultiply, 'mathJsMultiply')

console.log('test adding results...')

assert(String(roundAdd()) === '0.3')
assert(String(decimalAdd()) === '0.3')
assert(String(numeralAdd()) === '0.3')
assert(String(bigJsAdd()) === '0.3')
assert(String(mathJsAdd()) === '0.3')

console.log('test adding performance...')

test(roundAdd, 'roundAdd')
test(decimalAdd, 'decimalAdd')
test(numeralAdd, 'numeralAdd')
test(bigJsAdd, 'bigJsAdd')
test(mathJsAdd, 'mathJsAdd')


Results



roundMultiply: 2.673ms
withBigJs: 123.759ms
decimalMultiply: 172.068ms
withNumeral: 206.626ms
mathJsMultiply: 255.870ms

roundAdd: 2.317ms
mathJsAdd: 68.212ms
numeralAdd: 139.752ms
decimalAdd: 184.210ms
bigJsAdd: 222.685ms


As you can see, roundAdd and roundMultiply are far ahead of all other functions.



My main question: are there operands having at most two digits in fractional part and such, which, when peforming simple arithmetic operations (+, -, *, /) with them, whould give incorrect result when using Math.round? Because I can't see any reason why would I need to use any of those (or other libraries) taking into account their performance.







javascript math floating-point






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 19:04







gumkins

















asked Nov 13 '18 at 13:33









gumkinsgumkins

2,87142945




2,87142945













  • Possible duplicate of Is floating point math broken?

    – duffymo
    Nov 13 '18 at 15:04






  • 4





    @duffymo Come on, guys, this site becomes useless because each question is similar to some another question or contains similar keys in its subject or description. Do you really think that because that question is also about binary arithmetic inaccuracy there is no doubt that it contains answers will I ever be faced with errors because of Math.round usage instead of special JS library? Well, may be you think my question has not the best subject, in that case can you please suggest better one or what I should improve in it? Thanks

    – gumkins
    Nov 13 '18 at 18:54



















  • Possible duplicate of Is floating point math broken?

    – duffymo
    Nov 13 '18 at 15:04






  • 4





    @duffymo Come on, guys, this site becomes useless because each question is similar to some another question or contains similar keys in its subject or description. Do you really think that because that question is also about binary arithmetic inaccuracy there is no doubt that it contains answers will I ever be faced with errors because of Math.round usage instead of special JS library? Well, may be you think my question has not the best subject, in that case can you please suggest better one or what I should improve in it? Thanks

    – gumkins
    Nov 13 '18 at 18:54

















Possible duplicate of Is floating point math broken?

– duffymo
Nov 13 '18 at 15:04





Possible duplicate of Is floating point math broken?

– duffymo
Nov 13 '18 at 15:04




4




4





@duffymo Come on, guys, this site becomes useless because each question is similar to some another question or contains similar keys in its subject or description. Do you really think that because that question is also about binary arithmetic inaccuracy there is no doubt that it contains answers will I ever be faced with errors because of Math.round usage instead of special JS library? Well, may be you think my question has not the best subject, in that case can you please suggest better one or what I should improve in it? Thanks

– gumkins
Nov 13 '18 at 18:54





@duffymo Come on, guys, this site becomes useless because each question is similar to some another question or contains similar keys in its subject or description. Do you really think that because that question is also about binary arithmetic inaccuracy there is no doubt that it contains answers will I ever be faced with errors because of Math.round usage instead of special JS library? Well, may be you think my question has not the best subject, in that case can you please suggest better one or what I should improve in it? Thanks

– gumkins
Nov 13 '18 at 18:54












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53282190%2fwill-someone-ever-be-faced-with-wrong-results-of-simple-arithmetic-operations-on%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53282190%2fwill-someone-ever-be-faced-with-wrong-results-of-simple-arithmetic-operations-on%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Full-time equivalent

Bicuculline

さくらももこ