3

function roundUp(num, precision) {
  return Math.ceil(num * precision) / precision;
}

var num = 0.07;
var precision = 100;
console.log(roundUp(num, precision));

When the arguments to the function is 0.07 and 100, "num * precision" multiplication gives something like "7.000000000001" and ceil function rounds it up to 8. And I get a completely different result for no reason.

How can I fix this? I have big.js but couldn't work it out.

sabithpocker
  • 15,274
  • 1
  • 42
  • 75
brainmassage
  • 1,234
  • 7
  • 23
  • 42
  • 2
    http://0.30000000000000004.com/ – cartant Jan 18 '17 at 08:16
  • what result will be there? – Sanjay Jan 18 '17 at 08:20
  • Have a look at this: http://stackoverflow.com/questions/3072307/what-is-the-standard-solution-in-javascript-for-handling-big-numbers-bignum – ppasler Jan 18 '17 at 08:20
  • 1
    You have tagged this as bigdecimal, yet you are not using any bigdecimal library or data type, which would resolve your problem. Everybody above is pointing you towards floating point precision, which you will always encounter for standard floating point types (which are rounded to base 2, not base 10) – Dave Jan 18 '17 at 08:28

1 Answers1

0

Another naive attempt here as the function is ceiling. This attempts to make the error factor lower the number by EPSILON times so that we get 6.9999999.. instead of 7.00000000..1

Again perfectly naive attempt!

function roundUp(num, precision) {
      return Math.ceil((num * precision) - (num * precision * Number.EPSILON)) / precision;
}

console.log(roundUp(0.07, 100))
console.log(roundUp(0.03, 100))
console.log(roundUp(0.002, 1000))
console.log(roundUp(0.00222, 1000))
console.log(roundUp(0.006, 1000))
console.log(roundUp(0.00600000000000000000001, 10000000000000000000));//broken
console.log(roundUp(0.006001, 10000000));
console.log(roundUp(0.0333, 1000))
console.log(roundUp(0.07777777, 10))
console.log(roundUp(0.07777777, 100))
console.log(roundUp(0.07777777, 1000))
console.log(roundUp(0.07777777, 10000))
console.log(roundUp(0.07777777, 100000))
console.log(roundUp(0.07777777, 1000000))

console.log(roundUp(0.33333333333333, 1000000))
sabithpocker
  • 15,274
  • 1
  • 42
  • 75
  • This may provide "correct" value in OP's case but will certainly end up with "incorrect" values in some other cases due to floating math imperfections. Furthermore, it would be extremely inefficient to convert every number to string and then back to number. – Andrew Sklyarevsky Jan 18 '17 at 08:38
  • Your use of toFixed is silly; you're converting the number to a base-10 string then immediately casting it back to a base-2 float. At best you luck out and get it to round the other way when it casts back, but that's just through chance really. – Dave Jan 18 '17 at 08:39
  • @AndrewSklyarevsky ,Dave I agree with both of your observations. I usually see the EPSILON factor after may be 10-12 decimal digits, so a naive attempt to waive off that part. Im sure this is not accurate as you guys mentioned. – sabithpocker Jan 18 '17 at 08:44