5

Consider the following:

#include <iostream>
#include <cmath>
int main()
{
  using std::cout;
  using std::endl;

  const long double be2 = std::log(2);
  cout << std::log(8.0) / be2 << ", " << std::floor(std::log(8.0) / be2)
      << endl;

  cout << std::log(8.0L) / be2 << ", " << std::floor(std::log(8.0L) / be2)
      << endl;
}

Outputs

  3, 2
  3, 3

Why does the output differ? What am I missing here?

Also here is the link to codepad: http://codepad.org/baLtYrmy

And I'm using gcc 4.5 on linux, if that's important.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
user803563
  • 408
  • 3
  • 11

3 Answers3

4

When I add this:

cout.precision(40);

I get this output:

2.999999999999999839754918906642444653698, 2
3.00000000000000010039712117215771058909, 3

You're printing two values that are very close to, but not exactly equal to, 3.0. It's the nature of std::floor that its results can differ for values that are very close together (mathematically, it's a discontinuous function).

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
2
#include <iostream>
#include <cmath>
#include <iomanip>

int main()
{
  using std::cout;
  using std::endl;

  const long double be2 = std::log(2);

  cout << setprecision (50)<<std::log(8.0)<<"\n";
  cout << setprecision (50)<<std::log(8.0L)<<"\n";
  cout << setprecision (50)<<std::log(8.0) / be2 << ", " << std::floor(std::log(8.0) / be2)
       << endl;
  cout << setprecision (50)<< std::log(8.0L) / be2 << ", " << std::floor(std::log(8.0L) / be2)
       << endl;

  return 0;
}

The output is:

2.0794415416798357476579894864698871970176696777344
2.0794415416798359282860714225549259026593063026667
2.9999999999999998397549189066424446536984760314226, 2
3.0000000000000001003971211721577105890901293605566, 3

If you check the output here, you will notice that there is a slight difference in the precision of the two outputs. These roundoff errors usually kick in on operations on float & double here while performing floor() and the results that appear are not what one feels they should be.

It is important to remember two attributes Precision & Rounding when you are working with float or double numbers.

You might want to read more about it in my answer here, the same reasoning applies here as well.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
2

To expand on what Als is saying-

In the first case you are dividing an 8-byte double precision value by a 16-byte long double. In the second case you are dividing a 16-byte long double by a 16-byte long double. This results in a very small roundoff error which can be seen here:

cout << std::setprecision(20) << (std::log(8.0) / be2) << std::endl;
cout << std::setprecision(20) << (std::log(8.0L) / be2) << std::endl;

which yields:

2.9999999999999998398
3.0000000000000001004

Edit to say: in this case, sizeof is your friend (To see the difference in precision):

sizeof(std::log(8.0));  // 8
sizeof(std::log(8.0L)); // 16
sizeof(be2);            // 16
MarkD
  • 4,864
  • 5
  • 36
  • 67