Strange off by 1 error

I'm running CodeBlocks 17.12, it's never given me any problems (I've only been using it for a semester though) and now all of a sudden it's giving me this weird off by 1 error. The code included should print 100 but instead, it prints 99. After some troubleshooting, I discovered that taking away "using namespace std" and instead using the shorthand "std::" fixes this error. Would like any input as to what could be the problem here. Thanks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//Gives an off by one error

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

int main()
{
    int x = pow(10,2);
    cout << x;
}


//Doesn't give an off by one error
/*
#include <iostream>
#include <cmath>

int main()
{
    int x = pow(10,2);
    std::cout << x;
}
*/
pow works with floating-point numbers and as always when working with floating-point numbers rounding errors has to be expected.

pow(10, 2) returns a double with a value that is very close to 100, but not necessarily exactly 100. If it is 99.999....something you will get 99 when converting it to an int. A solution might be to change x to a double. If x is supposed to be an int you could instead round the number to the closest integer before converting it to an int.

 
int x = std::round(std::pow(10, 2));
Last edited on
pow is slower than it needs to be for ints because it handles floats, and it can have roundoff problems. Many programmers write their own integer power routine for speed & precision both.

for 0-3 powers, you may be better off just doing x*x inline. For 4+ go ahead and write a function.
Last edited on
Might just be an issue with CodeBlocks, both give me a result of 100 on Visual Studio.
I would be curious to know the result if you posted the assembly of both programs using the -S flag.
https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-c-c-source-in-gcc

And what version of the compiler, and what optimization level is enabled.
I'm running the MinGW distribution of g++ (GCC) 7.2.0, and get 100 for both programs, with or without -O3.

According to this: http://www.codeblocks.org/downloads/26
The codeblocks-17.12mingw-setup.exe file includes additionally the GCC/G++ compiler and GDB debugger from TDM-GCC (version 5.1.0, 32 bit, SJLJ)

Assuming Windows, that runs TDM-GCC 5.1.0, which is from 2015. (Perhaps not technically a "bug", due to the inherent nature of floating-point, but less-than-optimal behavior).

Compilers like GCC implement their own versions of pow which they treat special. Perhaps because you didn't specify that you were using std::pow, it used the compiler's internal pow, which had a slightly different implementation. I don't actually know.
Last edited on
What happens if you use std::pow in your second version?
Thanks for the responses, much appreciated.

@Peter87 I was aware of how the pow function works and how it uses floating-point numbers. What's rather strange about this is that it doesn't output the same response in other compilers (www.onlinegdb.com, cpp.sh, Visual Studio).

@jonnin For my particular program I was writing I only need a power of two so I did end up doing what you suggested, just found intriguing as to why this was happening.

@Ganago @dutch After 30 minutes of trying to find where to type the -S flag command I've admitted defeat, I'm pretty new to programming. Even using std::pow I get 99. I was initially thinking it could be due to the nature of Peter's comment (integers rounding down to nearest whole number), but then again it works correctly for other compilers.

I don't know what the compiler is deciding behind the scenes in your case, but the key takeaway here is: Be aware that when you're dealing with floating-point numbers, the result may not be exactly what you expect. So when in doubt, if you're converting a floating-point to an integer, round it.
Last edited on
The interesting thing here is that he seems to be getting two different versions of pow. One is std::pow, which he gets if he uses namespace std or puts std:: in front of pow. That version returns 99.9... for an answer. The other is ::pow, which apparently returns 100.0... for an answer.

So presumably this version will print 100.

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    int x = ::pow(10,2);  // use global pow (not std::pow)
    cout << x << '\n';
}

In that case, the assembly may show no difference since the difference is that they link to different pow functions.
Last edited on
Dutch you are correct my friend. Using the global pow and not the standard one did print 100.
Topic archived. No new replies allowed.