1

I tried searching for the answer to this question but to no avail. What I am trying to do is count the 0s of cos(x) between 0 and a number provided by a user in radians. I'm new to c++, so be gentle if this is trivial.

This is an excerpt from my code, (also note I'm not exactly sure about the difference between #import and #include, but I digress).

#define _USE_MATH_DEFINES
#import <iostream>
#import <algorithm>
#include <math.h>
#include <stdio.h>

int count = 0;
if (r > 0) {
    for (float i = 0; i < r; i += M_PI_2) {
        printf("\n\n%s: %f: %f\n\n", cos(i) == -float(0) ? "true":"false", \
            cos(i), -float(0));
        if (cos(i) == float(0) || cos(i) == -0) {
            count++;
            printf("Count: %d", count);
        }
    }

Using the value 2R as r, I should get the count to increase once but the if statement evaluates to false. I'm not sure I should be casting float to zero, nor checking against -0. Anyway this is the output to the print statements in this snippet of code.

terminal snippet

It looks like cos(M_PI_2) in fact equals -float(0)so why does cos(M_PI_2) == -float(0) evaluate to false?? Again I just started to pick up c++ days ago, so my apologies if this is trivial.

NotMe
  • 77
  • 11
  • I think it's because of rounding errors. try `if (abs(cos(i)) < 0.00001)` – martijnn2008 Feb 12 '16 at 23:30
  • 4
    `#import` is not standard C++. – Pete Becker Feb 12 '16 at 23:31
  • 1
    see [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – M.M Feb 12 '16 at 23:33
  • Do not use `==` to compare floating-point values. [Most effective way for float and double comparison](http://stackoverflow.com/q/17333/995714) – phuclv Feb 12 '16 at 23:42
  • some suggestions: `0.0f` instead of `float(0)`, and `-0.0` instead of `-0` (that'll be different, because there's no negative zero in 2's complement – phuclv Feb 12 '16 at 23:44
  • note that `-0` is an integer and identical to `0` (even on systems with negative zero integers) ; to get floating point negative zero you should use `-0.0` – M.M Feb 12 '16 at 23:49
  • Change the two `%f`s to `%e` in the format specifier in the `printf` statement and run the program again. That will help clarify what's going on. – Pete Becker Feb 12 '16 at 23:56
  • Where does `#import ` come from? That's a new one... Top tip: if you're not sure about something, _don't write it_. – Lightness Races in Orbit Feb 13 '16 at 00:01

2 Answers2

5

This one side of the double-edged sword of floating point. Do not compare floating point values for equality or inequality. Instead, bracket the range of values for approximate matches:

abs(cos(i) - float(0)) <= 0.0001 ? "true":"false"
wallyk
  • 56,922
  • 16
  • 83
  • 148
  • This worked, thanks a lot! I will accept the answer as soon as I'm allowed. – NotMe Feb 12 '16 at 23:38
  • This applies brute force to hide the actual problem. As harold says in his answer, these two values should **not** be equal, so the equality test correctly fails. – Pete Becker Feb 12 '16 at 23:47
4

It was not printed accurately enough to show it's different than zero.

Note that the result really shouldn't be zero in the first place, so that's not what the problem is. pi/2 is clearly not a rational number, so definitely not representable as a floating point number (in any integer base, also including binary). The cosine of a number x close to pi/2 is roughly pi/2 - x, so the magnitude of the cosine of the nearest float to pi/2 would be roughly the magnitude of the difference between that float and the actual value of pi/2. Since pi/2 is a fairly large number (compared to all the floating point numbers smaller than it), that difference can be approximated (it is of course again not a rational number) without flushing it to zero.

harold
  • 61,398
  • 6
  • 86
  • 164
  • Thanks, I mistakenly used `pi/2`as a float. This made sense of the actual problem. But actually, if I want to increment a number by `pi/2` what should the type for that number be if not float, double? – NotMe Feb 12 '16 at 23:55
  • 1
    @NotMe it cannot be done with any finite precision math. This is not necessary to count the number of zeroes (that would be there in R) though, you can find that out without trying to visit them all. – harold Feb 13 '16 at 00:01