2

When I execute this code the value of ans1, ans2 is 50002896 and 50005000.
I know there is some issues with ceil function but was not able to figure out the exact cause.

#include <bits/stdc++.h>
using namespace std;
int main()
{
      long long ans1 = 0, ans2 = 0;

      for (long long i = 1; i <= 10000; i++)
      {
            ans1 = ans1 + ceil((float)i / 1);
            ans2 = ans2 + i;
      }
      cout << ans1 << " " << ans2 << endl;
}
wohlstad
  • 12,661
  • 10
  • 26
  • 39
Chinnmay B S
  • 77
  • 1
  • 5
  • 2
    `#include ` -- Include the proper header files, not this one. – PaulMcKenzie Nov 20 '22 at 06:29
  • It's probably because of `(float)` not because of `ceil`. `float` is not fully accurate. – user253751 Nov 20 '22 at 06:33
  • 3
    By not using the proper *standard* header files, plus the usage of `using namespace std;` without knowing what that non-standard header file is pulling, in, we don't know if it is `std::ceil` or `ceil` from the C runtime library. That's why using `bits...whatever` is a bad idea, let alone it isn't standard. – PaulMcKenzie Nov 20 '22 at 06:37
  • 3
    [Different results when using `std::ceil` and `ceil`](https://godbolt.org/z/brhs6sEhs) – PaulMcKenzie Nov 20 '22 at 06:40
  • @PaulMcKenzie Without the `cmath` header, compilation fails with `c++11`, `c++14`, `c++17`, and `c++20` flags: error: 'ceil' is not a member of 'std' — I'm not sure how `ceil()` and `std::ceil()` differs. – Rohan Bari Nov 20 '22 at 06:45
  • 1
    @RohanBari There is no guarantee of compilation if you don't include the proper header files. – PaulMcKenzie Nov 20 '22 at 06:47
  • @PaulMcKenzie Sidenote, using `ceil`(no `std::`) can also result different results based on importing `` or `` – Ranoiaetep Nov 20 '22 at 07:17
  • @Ranoiaetep -- Yes, that's why using the non-standard "include everything" header is problematic. – PaulMcKenzie Nov 20 '22 at 07:32
  • @Chinnmay B S Why a `float` cast in `ceil((float)i / 1)` instead of `double` or `long double`? – chux - Reinstate Monica Nov 20 '22 at 07:34
  • Also, instead of using the `ceil((some_float / 1))` to cast a floating point number to integer, use `std::lround` and `std::llround` instead. – Ranoiaetep Nov 20 '22 at 07:48
  • 2
    [Why should I not `#include `?](https://stackoverflow.com/q/31816095/995714), [Why is `using namespace std;` considered bad practice?](https://stackoverflow.com/q/1452721/995714) – phuclv Nov 20 '22 at 10:32

2 Answers2

2

The source of the problem is not the ceil function, but rather that not all integers can be represented accuratly as floating point values.

Some more info about floating point representation: Wikipedia IEEE 754. And a related post: Which is the first integer that an IEEE 754 float is incapable of representing exactly?.

The following code is a minimal demonstration of the same issue that causes your issue:

float f1 = 100000000;
f1++;
std::cout << std::to_string(f1) << std::endl;

[Wrong] Output (expected: +1):

100000000.000000

One approach would be to use double instead of float.
This will not solve the principle issue, but will make the range of representable integers a lot bigger:

double f1 = 100000000;
f1++;
std::cout << std::to_string(f1) << std::endl;

Output:

100000001.000000

Some side notes:

  1. better to avoid #include <bits/stdc++.h> - see here: Why should I not #include <bits/stdc++.h>?.
  2. better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
wohlstad
  • 12,661
  • 10
  • 26
  • 39
1

First, try to use specific headers like #include , in this case, .because #include <bits/stdc++.h> will bring lots of junk.

So the issue is with float not ceil explained below

floating-point values do not represent exact values.

Code:-

#include <iostream>
#include <iomanip>
using namespace std;

// Driver Code
int main()
{
    float num1 = 10000.29;
    float num2 = 10000.2;

    // Output should be 0.0900000000
    cout << std::setprecision(15)
        << (num1 - num2);
    return 0;
}

Output :-

0.08984375

Sammed
  • 66
  • 7