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Јовић
  • 59,719
  • 40
  • 167
  • 261
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
  • 242,098
  • 41
  • 402
  • 602
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
  • 196,531
  • 48
  • 417
  • 525
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,654
  • 2
  • 28
  • 61