-1

M_PI is a macro which is defined as 3.14159265358979323846, which seems more precise than a double. I'm trying to get the answer in a float and no amount of casting will help me, the result is always 6.12323426e-017 or -4.37113883e-008 if i try and cast M_PI to a float.

The answer should be 0 and I would like to store that in a float.

cool mr croc
  • 725
  • 1
  • 13
  • 33
  • That seems exactly as precise as a double. – Teepeemm Nov 21 '14 at 15:38
  • The only rational number `x` for which `cos(x)` is rational is `0`. All floating-point numbers are rational; indeed, they are rationals whose denominator is a power of two. Your expectations are wrong, not your library's cosine implementation. – tmyklebu Nov 21 '14 at 17:52

3 Answers3

3

That's impossible. There's no way to represent the exact value of pi in a finite floating-point data type.

In general, you can't expect any operation on floating-point values to be exactly equal to the corresponding mathematical operation on real values. The usual approach is to compare with a tolerance, in this case perhaps something like

if (std::abs(result) < tolerance) {
    // treat it as zero
}

Choosing a suitable value of tolerance to get the accuracy you need for your particular problem is the hard part.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • 2
    Just to add - there are `FLT_EPSILON` and `DBL_EPSILON` in ``. – Paul Nov 21 '14 at 15:19
  • 3
    @Paul: In some circumstances they might be a reasonable guide to a sensible tolerance (if you expect an answer of around 1). But in general you'll need to analyse your problem, and the likely range of values you're dealing with, to find a suitable tolerance that might be very different to these values. – Mike Seymour Nov 21 '14 at 15:21
  • @Paul: You know what those are, right? And you know why they're not just tolerances that you use willy-nilly, right? – tmyklebu Nov 21 '14 at 17:46
1

The fact that the M_PI macro uses more precision than a double has, does not change the fact that the argument of the cos function, M_PI/2 is calculated as a double.

So, instead of calculating the cosine of the exact number 'pi/2', which is 0, you're calculating the cosine of the floating-point number closest to 'pi/2'. The result will therefore be not exactly 0.

No amount of casting will change that.

Jeffrey Sax
  • 10,253
  • 3
  • 29
  • 40
-1

Since the floating point representation of pi will never be any closer to pi than machine epsilon, the cosine of that value over two will be similarly different from the expected result of 0. Mathematically, the floating point value of pi can be represented as pi + eps, and thus the value of the function call will be

  cos(pi/2 + eps/2) = -sin(eps/2) ~= -eps/2.
sfjac
  • 7,119
  • 5
  • 45
  • 69
  • Don't understand the down vote - just trying go explain to the OP that the result of cos(M_PI/2) is expected to be a small number. – sfjac Nov 21 '14 at 20:41