-1

Can you help me with this task? I have a problem with rounding numbers to several decimal places.

This is my code:

function going(n) {
  let x = 1 / factorial(n);
  let y = 0;
  for(let i = 1; i <= n; i++){
    y += factorial(i);
  }
  return (x*y);
}

function factorial(n) {
  let br = 1;
  for(let i = 1; i <= n; i++){
    br *= i;
  }
  
  return br;
}

For n equal to 6 the result should be 1.2125 however I get 1.2125000000000001.

1.0000989217538616 will be truncated to 1.000098

1.2125000000000001 will be truncated to 1.2125

How do I solve it? These are the required results for the other values of the variable n.

(going(5), 1.275)
(going(6), 1.2125)
(going(7), 1.173214)

For each of these examples, the number of digits to be rounded is different. Note the return value should be a number and not a string!

I tried to solve the problem through these functions but it didn't work:

toExponential()
toFixed()
toPrecision() and Number
parseFloat(), parseInt()
  • 2
    See [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Unmitigated Jun 21 '23 at 01:24
  • You can fix `going(6)` by changing `x = 1/factorial(n)` to `x = factorial(n)` and `(x * y)` to `y / x`, which gets rid of one operation, and one corresponding intermediate state, reducing the error. However, there is no guarantee there would not be similar errors elsewhere; if you hate it, the only recourse is not using floating-point numbers and getting a decimal library like decimal.js. About the third case: why should `1.1732142857142858` be truncated to `1.173214`, and not e.g. `1.1732` or `1.1732143`? it is not a matter of floating point error like the `1.2125000000000001` case. – Amadan Jun 21 '23 at 01:33

1 Answers1

1

The issue you're facing is related to the limitations of floating-point arithmetic in JavaScript. Due to the way floating-point numbers are represented in binary, some decimal values cannot be precisely represented, leading to small rounding errors.

To address this problem and round the result to the desired number of decimal places, you can use the toFixed() method. However, you need to convert the final result back to a number from the string that toFixed() returns.

Here's an updated version of your code that incorporates this approach:

function going(n) {
  let x = 1 / factorial(n);
  let y = 0;
  for (let i = 1; i <= n; i++) {
    y += factorial(i);
  }
  
  let result = x * y;
  
  return Number(result.toFixed(n));
}

function factorial(n) {
  let br = 1;
  for (let i = 1; i <= n; i++) {
    br *= i;
  }
  
  return br;
}

In this updated code, the toFixed(n) method is used directly on the result variable, where n is the desired number of decimal places for rounding. The Number() function is then used to convert the rounded string back to a number.

Now, when you call going(5), it will round the result to 5 decimal places (1.275), for going(6) it will round to 6 decimal places (1.2125), and for going(7) it will round to 7 decimal places (1.173214). The rounding is based on the n parameter itself.

aleksandar
  • 186
  • 12
  • I did it. However, it doesn't work for all cases, like for example: "expected 1.146652 to equal 1.146651" "expected 1.112741 to equal 1.11274" – Dusan Pavlovic Jun 21 '23 at 01:40
  • Well, the reason for the behavior you're seeing is explained in the link provided in that first comment. You could try to improve the precision of rounding, you can use a workaround by multiplying the number by a power of 10, performing the rounding, and then dividing by the same power of 10. – aleksandar Jun 21 '23 at 09:07
  • 1
    Copy-paste from ChatGPT – DavidW Jun 21 '23 at 21:48
  • Welcome back to Stack Overflow. It looks like it's been a while since you've posted and may not be aware of the current policies since you posted 7 answers today, most or all of which appear likely to have been entirely or partially written by AI (e.g., ChatGPT). Please be aware that [posting of AI-generated content is banned here](//meta.stackoverflow.com/q/421831). If you used an AI tool to assist with any answer, I would encourage you to delete it. Thanks! – NotTheDr01ds Jun 21 '23 at 21:49
  • **Readers should review this answer carefully and critically, as AI-generated information often contains fundamental errors and misinformation.** If you observe quality issues and/or have reason to believe that this answer was generated by AI, please leave feedback accordingly. The moderation team can use your help to identify quality issues. – NotTheDr01ds Jun 21 '23 at 21:49