18

While running the following lines of code:

int i,a;    

for(i=0;i<=4;i++)  
{    
    a=pow(10,i);    
    printf("%d\t",a);    
}   

I was surprised to see the output, it comes out to be 1 10 99 1000 9999 instead of 1 10 100 1000 10000.

What could be the possible reason?

Note
If you think it's a floating point inaccuracy that in the above for loop when i = 2, the values stored in variable a is 99.

But if you write instead

a=pow(10,2);

now the value of a comes out to be 100. How is that possible?

Suraj Jain
  • 4,463
  • 28
  • 39
Kroor Singh
  • 255
  • 2
  • 7
  • What platform and compiler did you observe this on? I tried to [reproduce it on ideone](http://ideone.com/ENTban), but apparently their implementation of `pow()` returns exact results for positive integer powers of 10. – Ilmari Karonen Aug 09 '13 at 21:35
  • 5
    Note that a reasonable C compiler would provide a **faithful** `pow()` function, with which this problem would not happen. http://blog.frama-c.com/index.php?post/2013/04/06/Non-experts-need-accurate-floating-point-the-most – Pascal Cuoq Aug 09 '13 at 21:39
  • i used dev c++ 4.9.9.2 – Kroor Singh Aug 09 '13 at 21:40
  • If you want small integer powers of 10, you're better off writing your own function that does repeated multiplication. – Keith Thompson Aug 09 '13 at 21:59
  • 3
    @PascalCuoq: +1 for blaming the bad implementation, but to be precise, this is a matter of the library implementation, not the compiler. – R.. GitHub STOP HELPING ICE Aug 09 '13 at 22:49
  • Apart from floating point inacuracy and casting to and fro, `#include ` will probably help a bit. – wildplasser Aug 09 '13 at 23:01
  • possible duplicate of [What is a simple example of floating point/rounding error?](http://stackoverflow.com/questions/249467/what-is-a-simple-example-of-floating-point-rounding-error) –  Aug 13 '13 at 20:00
  • Duplicate thousands of times (literally)... **DO NOT** use `pow()` for integer exponentation. `p = 1; while (exponent-- > 0) p *= base;` is **the** solution. –  Aug 13 '13 at 20:02
  • 1
    the `pow()` does returns double which round of the value 100 as 99.9999. And when you print this value as integer it shows 99 – Vighanesh Gursale Aug 15 '13 at 06:50
  • possible duplicate of [Why pow(10,5) = 9,999 in C++](http://stackoverflow.com/questions/9704195/why-pow10-5-9-999-in-c) – phuclv Sep 06 '15 at 05:22
  • 1
    @SurajJain You are using comments to ask a new question, which is a terrible idea. Please ask a new question, which will be answered by whoever has the time and knows the answer. – Pascal Cuoq Oct 10 '16 at 17:20
  • @SurajJain among the reasons why what you are doing is a terrible idea: - your comment does not have a tag indicating which programming language you mean - there is no voting system on comments to tell that it's a good question, or that an answer you receive in a comment is a good answer - literally no-one except two very busy persons will see your comment - there is no space for a detailed answer in a comment - a recent visitor to the site, if they happened to stumble onto your comment, would not be able to post the answer because they wouldn't have the reputation for commenting. – Pascal Cuoq Oct 10 '16 at 17:22
  • @SurajJain: Then you need to find out how to get the question ban removed. (Hint: Compile-time optimization.) – Keith Thompson Oct 10 '16 at 19:35
  • @PascalCuoq Sir , i need to talk with you, can we chat ? – Suraj Jain Feb 09 '17 at 10:15
  • @SurajJain **AGAIN**, this is not how this site works. – Pascal Cuoq Feb 11 '17 at 19:54
  • @PascalCuoq I then had something to ask for and so i thought if we could chat in chat room. How to chat with someone then ? – Suraj Jain Feb 12 '17 at 01:56
  • Your question is legitimate and answers here tells why it is so http://stackoverflow.com/questions/42164550/what-is-happening-here-in-pow-function – Suraj Jain Feb 19 '17 at 07:46

5 Answers5

22

You have set a to be an int. pow() generates a floating point number, that in SOME cases may be just a hair less than 100 or 10000 (as we see here.)

Then you stuff that into the integer, which TRUNCATES to an integer. So you lose that fractional part. Oops. If you really needed an integer result, round may be a better way to do that operation.

Be careful even there, as for large enough powers, the error may actually be large enough to still cause a failure, giving you something you don't expect. Remember that floating point numbers only carry so much precision.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • 4
    Yeah, the important thing is that converting to `int` like this truncates rather than rounds. – Crowman Aug 09 '13 at 21:29
  • 1
    then how is it possible that the same funcion produces an output 100 when you simply write a=pow(10,2); (instead of 99 which is produced in the for loop for i=2) – Kroor Singh Aug 10 '13 at 14:46
  • 2
    @MayankJha It's not **required** that there **be** an error. It's only possible. For certain values. –  Aug 13 '13 at 20:03
  • 2
    @MayankJha: because when dealing with floating point numbers, there is no requirement that constant literals have the same rounding precision as variables with the same value. So the compiler is free to evaluate the constant expressions at compile time with more precision and get a slightly different result, which ends up being very different with the truncate. – Chris Dodd Aug 13 '13 at 20:09
  • @ChrisDodd Sir , the person asked that in question and no one has answered it with this thing compiler optimization , can you ? – Suraj Jain Feb 12 '17 at 11:52
  • @MayankJha Check This Question It will tell why pow(10,2) result come different. http://stackoverflow.com/questions/42164550/what-is-happening-here-in-pow-function – Suraj Jain Feb 19 '17 at 07:45
  • It should be noted that this is a defect in the `pow` implementation being used. When a mathematical result is exactly representable, a good `pow` implementation returns the exact result. – Eric Postpischil Jan 21 '18 at 15:42
14

The function pow() returns a double. You're assigning it to variable a, of type int. Doing that doesn't "round off" the floating point value, it truncates it. So pow() is returning something like 99.99999... for 10^2, and then you're just throwing away the .9999... part. Better to say a = round(pow(10, i)).

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
  • or `(int)(pow(10,i)+0.5)` (rough equivalent of round) – technosaurus Aug 09 '13 at 21:33
  • OP's `pow()` has surprising weaknesses. – chux - Reinstate Monica Aug 09 '13 at 22:17
  • But when i assign variable `a` of type `float ` to `pow()` . It returns `100.000000` instead of `99.9999999` why so ? – Suraj Jain Jul 27 '16 at 02:50
  • @chux But when i assign variable a of type float to pow() . It returns 100.000000 instead of 99.9999999 why so ? – Suraj Jain Aug 24 '16 at 17:30
  • @Suraj Jain C does not specify the quality of `pow()` results. High quality implementations (like yours) would return 100.0 on `pow(100,2)`. Lower quality ones (like OP's) may return a few [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place) off from expectations like 99.999999999999985..., Detail: Op's code does not involve `float`. The typically `floats values before/after 100.0f are 99.9999924... and 100.0000076... instead of 99.9999999 – chux - Reinstate Monica Aug 24 '16 at 18:22
9

This is to do with floating point inaccuracy. Although you are passing in ints they are being implicitly converted to a floating point type since the pow function is only defined for floating point parameters.

DrYap
  • 6,525
  • 2
  • 31
  • 54
  • 7
    The article you link to describes the representation of floating-point numbers and some of the principles behind them, but it is not relevant here because both the argument and the result of `pow(10, 2)` are exactly representable as `double`. Instead, the OP is using an inferior implementation of `pow()`, a topic not addressed in the article. – Pascal Cuoq Aug 09 '13 at 21:47
1

Mathematically, the integer power of an integer is an integer.

In a good quality pow() routine this specific calculation should NOT produce any round-off errors. I ran your code on Eclipse/Microsoft C and got the following output:

1   10  100 1000    10000   

This test does NOT indicate if Microsoft is using floats and rounding or if they are detecting the type of your numbers and choosing the appropriate method.

So, I ran the following code:

#include <stdio.h>
#include <math.h>
main ()
{
    double i,a;

    for(i=0.0; i <= 4.0 ;i++)
    {
        a=pow(10,i);
        printf("%lf\t",a);
    }
}

And got the following output:

1.000000    10.000000   100.000000  1000.000000 10000.000000    
JackCColeman
  • 3,777
  • 1
  • 15
  • 21
  • 1
    The second test would be more conclusive with `double a;` than with `float a;`. As written, your test is only checking that `pow()` is not wrong by 2^28 ULPs, which I hope even the OP's implementation isn't. – Pascal Cuoq Aug 09 '13 at 23:41
  • @PascalCuoq according to the question `pow()` is wrong by 1.0 – JackCColeman Aug 10 '13 at 05:15
  • 2
    The only thing we can deduce from the OP's information is that `pow(10,2)` is below `100` by at least one ULP. C's truncation behavior when converting `double` to `int` does the rest. In your second test program, however, the implicit conversion from `double` to `float` is to the nearest, so that your program would only reveal an issue if `pow()` was wrong by half the value of the `float` ULP, which represents 2^28 `double` ULPs. – Pascal Cuoq Aug 10 '13 at 05:31
  • @PascalCuoq changed to double and got the same result, as expected. Believe it or not Microsoft does a good job, at least compared to gcc and the like. – JackCColeman Aug 10 '13 at 06:01
  • `%lf` shows only a limited number of digits. The `double` value supplied to it is rounded to that number of digits. So the printed output does not show the true value. Therefore, this code does not demonstrate that the values of `pow(10, i)` are 1, 10, 100, 1000, and 10000. – Eric Postpischil Jan 06 '19 at 16:04
  • Update and run the test to display more digits and let me know the result. Post the code so that I can recreate your results. Remember: Trust but Verify! – JackCColeman Jan 07 '19 at 22:31
1

No one spelt out how to actually do it correctly - instead of pow function, just have a variable that tracks the current power:

int i, a, power;    

for (i = 0, a = 1; i <= 4; i++, a *= 10) {    
    printf("%d\t",a);    
}

This continuing multiplication by ten is guaranteed to give you the correct answer, and quite OK (and much better than pow, even if it were giving the correct results) for tasks like converting decimal strings into integers.