-4

The following code displays -2.38419e-07 instead of 0. However, on replacing int(arr[i]) with (arr[i]/1), it shows the correct output. Why?

#include <bits/stdc++.h>
using namespace std;

int main() {

    float arr[4] = {4.58413, 1.22491, -2.10517, -3.70387};

    float fsum = 0.00000;
    for(int i=0; i<4; ++i) fsum += (arr[i]-int(arr[i]));
    cout << fsum << endl;

    return 0;
}
Trial
  • 46
  • 5
  • 3
    **Recommended reading:** [Why should I not #include ?](https://stackoverflow.com/q/31816095/560648) – Lightness Races in Orbit Jun 28 '19 at 13:35
  • `(arr[i]/1)` is the same as `arr[i]`, so in that case `fsum` is zero at every step, no matter what the inputs are. – aschepler Jun 28 '19 at 13:35
  • 1
    @molbdnilo The sum of all the fractional parts is zero. In theory. Ish. – Lightness Races in Orbit Jun 28 '19 at 13:35
  • @molbdnilo: Because mathematically, these 4 numbers add up to zero. Both the integer and fractional parts cancel out. – MSalters Jun 28 '19 at 13:36
  • 1
    (Lightness and MSalters refer of course to the decimal numbers described by the source code literals, which are not the same as the `float` values.) – aschepler Jun 28 '19 at 13:37
  • @LightnessRacesinOrbit You're quite the mental arithmeticist. – molbdnilo Jun 28 '19 at 13:37
  • Verify your assumption that the two are equivalent: `int main() { std::cout << int(4.58413f) << '\n' << 4.58413f/1 << '\n'; }` – molbdnilo Jun 28 '19 at 13:48
  • @LightnessRacesinOrbit ... and [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721) – L. F. Jun 28 '19 at 13:57
  • 1
    @L.F. Yes (although to be honest that's much less evil!) – Lightness Races in Orbit Jun 28 '19 at 14:00
  • did you expect `(arr[i]/1)` to result in the fractional part of the numbers? That would be `fmod( arr[i] , 1)` (not `arr[i] % 1` as `%` only works for integers) – 463035818_is_not_an_ai Jun 28 '19 at 14:02
  • 3
    @formerlyknownas_463035818 Looks more like they expected it to result in the integral part of the numbers, since they changed it from `int(arr[i])`. I can kind of see where that would come from (in the absence of basic study and research, that is), since we stick a `1.0` on the RHS to force floating-point division (well, we don't, because division by 1 is silly, but y'know) – Lightness Races in Orbit Jun 28 '19 at 14:06

2 Answers2

2

The following code displays -2.38419e-07 .... Why?

(Assuming your system uses IEEE-754 binary32 floating point) It just so happens that none of those floating point literals can be represented exactly on your system. You are not adding together those numbers that you've written. You're adding together these numbers, which are representable, and are quite close to your literals, but not exactly:

4.584129810333251953125
1.2249100208282470703125
-2.1051700115203857421875
-3.7038700580596923828125

In short: Not all numbers are representable in finite floating point representations, and if your input values cannot be represented exactly, then there will be precision errors in your floating point calculations. There are other causes for floating point accuracy errors too, which don't necessarily apply here.

However, on replacing int(arr[i]) with (arr[i]/1), it shows [output 0]. Why?

Because arr[i]/1 is same as arr[i] and arr[i] - arr[i] is 0 and 0 + 0 + 0 + 0 is 0.

If you calculate something else, then it should hardly be surprising that the result is something else.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

The broken code

You're almost at zero. Floating-point fractions are often imprecise, so you have a rounding problem.

Only you can decide how to fix that. You could say that any error smaller than, say, 0.00001 is "close enough".

Ultimately, you will always have some kind of rounding error when doing maths like this on floating-point values. Try to stick to fixed-point if you can.


The working code

Actually, this is also broken.

arr[i]/1 is literally the same as arr[i] (it does not cast to int), so all you're doing is arr[i]-arr[i].

This will always be zero, even when you didn't want it to be!

Remember to verify your code with more than just one testcase. Test a range of inputs and outputs.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055