0

Consider the following MCVE:

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

int main()
{
    boost::multiprecision::cpp_int x = 10;
    x *= 10000000000000000000000000000000000000000000000000000000000000;
    std::cout<<x<<std::endl;
    return 0;
}

It produces a wrong result, due to the obvious overflow from that int. How can I do this correctly, assuming I don't want to involve strings? Is there something like a "digit shift operator" or a power function that can do this cheaply (or cheapest possible)?

Why? Because I have a fixed-precision library that I wrote, and scaling the internal integer requires such operations to be 100% safe.

Find the example here.

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
  • If you downvote, say why please and explain how to improve the question. – The Quantum Physicist Jan 04 '19 at 21:12
  • Maybe a templated UDL can be used to create the integer. – Justin Jan 04 '19 at 21:15
  • @Justin Can you provide a link/reference please? – The Quantum Physicist Jan 04 '19 at 21:15
  • 1
    https://en.cppreference.com/w/cpp/language/user_literal it's a numeric literal operator template – Justin Jan 04 '19 at 21:18
  • @Justin Thanks. Looking into it. – The Quantum Physicist Jan 04 '19 at 21:20
  • @Justin: I just had a look at [the user-defined literals available in the boost::multiprecision class](https://www.boost.org/doc/libs/1_69_0/libs/multiprecision/doc/html/boost_multiprecision/tut/lits.html), and it seems that only hexadecimal literals are supported. This looks like a big misfeature to me; it wouldn't be hard to implement a decimal version, and it would solve the OP's problem. – TonyK Jan 04 '19 at 21:27
  • @TonyK I was almost arriving to the same conclusion... you beat me to it. That's really disappointing! Sounds like strings are the only way to solve this... – The Quantum Physicist Jan 04 '19 at 21:29
  • 1
    Or you might like to have a go at writing your own user-define literals. [Here is a question I posted not long ago](https://stackoverflow.com/q/53913800/428857) about this very topic. – TonyK Jan 04 '19 at 21:56

1 Answers1

1

You'll want a function to auto-generate the number you need.

boost::multiprecision::cpp_int pow(boost::multiprecision::cpp_int value, boost::multiprecision::cpp_int exponent) {
    if(exponent <= 0)
        return 1;
    else if(exponent == 1)
        return value;
    else {
        if(exponent % 2 == 0) {
            return pow(value * value, exponent / 2);
        } else {
            return value * pow(value, exponent - 1);
        }
    }
}

int main()
{
    boost::multiprecision::cpp_int x = 10;
    x *= pow(10, 61);//I believe this is the correct number of 0's from manually counting
    std::cout<<x<<std::endl;
    return 0;
}

If boost.multiprecision has a baked in pow function (I couldn't find one), use that instead.

Xirema
  • 19,889
  • 4
  • 32
  • 68
  • Unfortunately, there's no `pow` for integers in the standard, which will incur precision problems. This, besides that using a string is much cheaper than these many multiplications. Thanks for the attempt to help anyway. – The Quantum Physicist Jan 04 '19 at 21:43
  • If I am not wrong, we get 9 multiplications for `10^61` calculation. Not so many ... – Damien Jan 05 '19 at 06:57