[SOLVED] Is there possibly an inconsistency in pow function?
I was trying to enumerate powers of a certain number <N>. I am doing this by multiplying <N> by itself using a loop, so far it's fine. To verify the result, I generate what was supposedly the very same number by using pow(<N>, <counter> - 1). Everything looks fine in the beginning of the code output, but the few last numbers given by pow() function are different. I have tested this problem with a few (one-digit) numbers, but so far, the symptom showed in all the numbers I tested (except when <N> = 2) Am I doing something wrong in calling pow() or is it something inside? Here's the code, Thank you in advance 🙏 https://code.sololearn.com/c0ptmo2qCwxW/?ref=app
12/3/2020 4:45:38 AMIpang
21 AnswersNew Answer
There are more integers in long long ints than there are in double. Why? Because a long long int has 63 bits, the mantissa of a double has 52 + 1 bits. So, think of a double as a 53bit integer. Now, pow returns a double, that is, you get a precision of about 15 or 16 significant digits, or so. After that, you're on your own. The result you get from pow is probably the integer closest to the actual result that is still representable with a 52bit mantissa + 1 and exponents. Besides that, the pow funcion has for integer use notoriously been known to be shaky. I have always recommended to implement a custom integer version in lieu of the library one.
[3 of 3] So what has happend is the in the pow() function, it is only accurate to 16 significant digits, but if you use long long you can get more..... I think it makes a bit sense.. I know you have already got your answer but might this will help a bit more/less .. Hope helps a bit✌️
[2 of 3] So what is the difference between "long long" and "int" that makes "long long" better to deal with big integers? Coz The long long takes twice as much memory as long...is this what you thought? Now see that a "double" takes as much memory as a "long long" - But some of that memory is used to hold the "matissa" and some the "exponent". The mantissa is 53 bits.So with 53 bits, you can only hold 15 or 16 decimal digits of precission. The 64 bits of the "long long" can hold 24 decimal digits of a number....
Hii Ipang [1 of 3] Here's the output - $ ./main 1. 1 1 2. 5 5 3. 25 25 4. 125 125 5. 625 625 6. 3125 3125 7. 15625 15625 8. 78125 78125 9. 390625 390625 10. 1953125 1953125 11. 9765625 9765625 12. 48828125 48828125 13. 244140625 244140625 14. 1220703125 1220703125 15. 1808548329 -2147483648 Ok so the right hand column (the one with integer math) is wrong. and it is wrong after 15 counts!
Seems interesting though. May be this is because the way pow() handles large numbers is different, and because of that, long long int are shown differently. When you are brute-forcing, its clear to you what you are doing, so you handle it correctly, but may be in pow() large numbers cause overflow sort of thing.  As far my observation, as the numbers increase, the error increases by a larger factor.
Ipang I'm saying, when you calculated answer using ur own method(bruteforce), then u got correct answer.
Chiku Thanks to Coder Kitten rather me buddy! And I'm marking this thread solved now. I have come to a conclusion, that in C or C++, pow() function is the way for floating point numbers, but not so for integrals. We are better off with our own implementation 😁 Thanks to everyone who contributed 🙏
Thank you Coder Kitten for your answer. Really helpful ❤
You're both welcome. Also note that I edited my pevious answer a bit.
Chiku I'm raising this question because this problem makes me feel a bit insecure in using built-in function, while we are encouraged to avoid reinventing what was already available. Are you saying pow() function uses brute-forcing algorithm? I didn't get the second paragraph ...
Chiku If you mean the multiplication then yes, you are right! I checked the different numbers in Python and the result by multiplication was right, but the one by pow() was not. Thanks a bunch buddy! 🙏
Ipang thanks to u too for asking this cool question. It was really helpful.
Ipang yup 🤘
Easiest way to see it is to realise that 5² = 25 is congruent 25 modulo 100, 5³ = 5*5² = 125 is congruent 25 modulo 100. So, 5² eats up fives without changing in the last two digits.
Well, looks like 6 ends in 6 ☺ Also 76 ends in 76. There is a way to investigate this systematically - but it is getting a little mathy as you can imagine...
My calculations suggested 76. Four two-digit endings, actually, 00, 01, 25, and 76.
Piyush[21 Dec❤️] In Code Playground the first different output is obvious starting at 24th result (when using `long long` and <N> value 5). If we use `int` then different output starts earlier at 14th result (as you have shown). Did anyone notice how the powers of 5 (starting from 5**2) end with 25? is that a pattern or what? looks like powers of different <N> ends with different digits though 😁
Piyush[21 Dec❤️] I just saw your message FYI DMs don't work for me I can't reply 😁
Coder Kitten // 1 ends with <time limit warning> // 2 ends with sequence 2, 4, 8, 6 // 3 ends with sequence 3, 9, 7, 1 // 4 ends with sequence 4, 6 // 5 ends with 25 // 6 ends with sequence 6, 36, 16, 96, 76 // 7 ends with sequence 7, 9, 3, 1 // 8 ends with sequence 8, 4, 2, 6 // 9 ends with sequence 9, 1 5 and 10 are the ones with constants last digit(s). It's just looking different amongst other one-digit numbers tested, that's why it stands out 😁
Coder Kitten I also believed it is mathy under the hood, can't imagine myself digging that far knowing my limits 😂 Got a bad result at end for 11, didn't go higher than 11 because of it anyways. You tested 76?