1

My general task is to compute the sum of a set of positive integers, each multiplied by descending powers of 36, with the first power being the size of the set - 1According to Wolfram,
LaTeX for https://www.wolframalpha.com/input/?i=9*36%5E6%2B13*36%5E5%2B19*36%5E4%2B6*36%5E3%2B7*36%5E2%2B8*36%2B2

I expected the following to return the same:

#include <iostream>
#include <vector>
#include <math.h>

unsigned long long f(const std::vector<unsigned> &coefficients)
{
    unsigned short exponent = coefficients.size() - 1;
    unsigned long long sum;
    for (unsigned i : coefficients)
    {
        sum += i * pow(36, exponent);
        --exponent;
    }
    return sum;
}

int main()
{
    std::cout << f({9,13,19,6,7,8,2});
}

but instead it returns 20416905041. The minimum capacity of an unsigned long long integer is 0 to 18446744073709551615, according to Alex B on this question, so capacity doesn't appear to be the problem.


Specifications:
  • Compiler: x86_64-w64-mingw32 from the Windows TDM-GCC Compiler Suite
  • Compiled via g++ mwe.cpp -std=c++11 -omwe
  • OS: Windows 10 Home
Mushroom Man
  • 400
  • 3
  • 18
  • 2
    `pow` is a floating point function and therefore will be susceptible to rounding errors. You should use integer variables (do repeated multiplication by `36`) instead. – M.M Nov 19 '18 at 02:52
  • 1
    see [Why does cmath pow give inaccurate answers?](https://stackoverflow.com/q/53159752/1708801) – Shafik Yaghmour Nov 19 '18 at 02:54
  • Another bug is that you never initialize `sum` (you should set it to `0` before doing `+=` on it) – M.M Nov 19 '18 at 02:55
  • @M.M Ah yes, because `sum` is local and therefore not zero-initialized. Also, thanks for the fix. – Mushroom Man Nov 19 '18 at 03:02
  • 2
    @MushroomMan `return std::accumulate(coefficients.begin(), coefficients.end(), 0LL, [&](long long sum, unsigned i) { return sum + i * pow(36, exponent--);});` -- Magic in one line. [Example](http://coliru.stacked-crooked.com/a/5883c9d3701bbe6c) – PaulMcKenzie Nov 19 '18 at 03:13

1 Answers1

1

From M.M's comment on the question:

pow is a floating point function and therefore will be susceptible to rounding errors. You should use integer variables (do repeated multiplication by 36) instead.

Mushroom Man
  • 400
  • 3
  • 18