1

The assignment of the value of the equation to the variable (second line inside the loop) is always less by 1 -on the first iteration only- although the equation (first line inside the loop) on its own calculates fine.

I am using MinGW compiler, codeLite software on a Windows machine.

#include <iostream>
#include <cmath>
#include <vector>

int main(){
    std::vector<int> elements_of_num {5, 0, 3};
    size_t power = 2;
    int n {0};
    for(int el: elements_of_num){
        std::cout << n + el * pow(10, power) << std::endl;
        n = n + el * pow(10, power);
        std::cout << n << std::endl;
        power--;
    }
    std::cin >> n;
    return 0;
}

Expected result: {500, 500} {499, 499} {503, 503}

Actual result: {500, 499} {499, 499} {502, 502}

Community
  • 1
  • 1
abdullah
  • 15
  • 6
  • [cannot reproduce](https://wandbox.org/permlink/MyeIsEAZcHcty7Q5) – Kerrek SB Apr 13 '19 at 14:52
  • Something is wrong with your environment, not your code. The expected result is: 500, 500, 500, 500, 503, 503. – JimPri Apr 13 '19 at 15:23
  • [Why pow(10,5) = 9,999 in C++](https://stackoverflow.com/q/9704195/995714), [Why a+=b*pow(10,c-i-1) == 99 c++?](https://stackoverflow.com/q/39756656/995714), [Why does pow(n,2) return 24 when n=5, with my compiler and OS?](https://stackoverflow.com/q/25678481/995714), [Why does gcc compiler output pow(10,2) as 99 not 100?](https://stackoverflow.com/q/25474351/995714)... – phuclv Apr 13 '19 at 15:44
  • it's a bad idea to use `pow` to calculate values from digits like that. Just iterate in reverse and then use `n = n*10 + el` which is much faster – phuclv Apr 13 '19 at 15:46

1 Answers1

1

It seems that your pow implementation is inaccurate for these values. I have managed to get the same results as you by forcefully making pow(10, power) inaccurate.

In case of the first variant in your code:

std::cout << n + el * pow(10, power) << std::endl;

The value of the expression is slightly less than 500. You can verify this by

 std::cout.precision(20);
 std::cout << n + el * pow(10, power) << std::endl;

I suspect that this will print something like:

499.99999499999995578

(Note that since your original code prints numbers with a lower precision, you are deceived to believe that the expression results with 500. However, the actual value is slightly smaller).

In the case of the second line of code:

n = n + el * pow(10, power);

the 499.99999499999995578 is assigned to an int variable, truncating the fraction and leaving you with 499. Everything goes south after that.

NOTE:

I don't think that IEEE 754 dictates how pow(10, 2) should be implemented, and in theory it can be implemented using eln(10)*2, which introduces inaccuracies. Moreover C++ does not mandates IEEE 754 conformance. This means that pow(10,2) could be inaccurate on some systems and make a small error down or up, just like in your case.

Solution:

Don't use pow at all, or else use round(pow(10, power)). In your case, it is better to use regular integer multiplication by 10.

Michael Veksler
  • 8,217
  • 1
  • 20
  • 33