'How to take input 128 bit unsigned integer in c++

I am new to c++. I want to take input a unsigned 128 bit integer using scanf and print it using printf. As I am new to c++ , I only know these two methods for input output. Can someone help me out?



Solution 1:[1]

You could use boost, but this library set must be installed yourself:

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

int main()
{
   using namespace boost::multiprecision;

   uint128_t v = 0;

   std::cin >> v; // read 
   std::cout << v << std::endl; // write

   return 0;
}

Solution 2:[2]

If you want to get along without boost, you can store the value into two uint64_t as such:

std::string input;
std::cin >> input;

uint64_t high = 0, low = 0, tmp;
for(char c : input)
{
    high *= 10;
    tmp = low * 10;
    if(tmp / 10 != low)
    {
        high += ((low >> 32) * 10 + ((low & 0xf) * 10 >> 32)) >> 32;
    }
    low = tmp;
    tmp = low + c - '0';
    high += tmp < low;
    low = tmp;
}

Printing then, however, gets more ugly:

std::vector<uint64_t> v;
while(high | low)
{
    uint64_t const pow10 = 100000000;
    uint64_t const mod = (((uint64_t)1 << 32) % pow10) * (((uint64_t)1 << 32) % pow10) % pow10;
    tmp = high % pow10;
    uint64_t temp = tmp * mod % pow10 + low % pow10;
    v.push_back((tmp * mod + low) % pow10);
    low = low / pow10 + tmp * 184467440737 + tmp * /*0*/9551616 / pow10 + (temp >= pow10);
    high /= pow10;
}
std::vector<uint64_t>::reverse_iterator i = v.rbegin();
while(i != v.rend() && *i == 0)
{
    ++i;
}
if(i == v.rend())
{
    std::cout << 0;
}
else
{
    std::cout << *i << std::setfill('0');
    for(++i; i != v.rend(); ++i)
    {
        std::cout << std::setw(8) << *i;
    }
}

Above solution works up to (including)

340282366920938463463374516198409551615
= 0x ffff ffff ffff ffff ffff ad06 1410 beff

Above, there is an error.

Note: pow10 can be varied, then some other constants need to be adjusted, e. g. pow10 = 10:

low = low / pow10 + tmp * 1844674407370955161 + tmp * 6 / pow10 + (temp >= pow10);

and

std::cout << std::setw(1) << *i; // setw also can be dropped in this case

Increasing results in reducing the maximum number for which printing still works correctly, decreasing raises the maximum. With pow10 = 10, maximum is

340282366920938463463374607431768211425
= ffff ffff ffff ffff ffff ffff ffff ffe1

I don't know where the error for the very highest numbers comes from, yet, possibly some unconsidered overflow. Any suggestions appreciated, then I'll improve the algorithm. Until then, I'd reduce pow10 to 10 and introduce a special handling for the highest 30 failing numbers:

std::string const specialValues[0] = { /*...*/ };
if(high == 0xffffffffffffffff && low > 0xffffffffffffffe1)
{
    std::cout << specialValues[low - 0xffffffffffffffe2];
}
else
{
    /* ... */
}

So at least, we can handle all valid 128-bit values correctly.

Solution 3:[3]

You can try from_string_128_bits and to_string_128_bits with 128 bits unsigned integers in C :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

__uint128_t from_string_128_bits(const char *str) {
    __uint128_t res = 0;
    for (; *str; res = res * 10 + *str++ - '0');
    return res;
}

static char *to_string_128_bits(__uint128_t num) {
    __uint128_t mask = -1;
    size_t a, b, c = 1, d;
    char *s = malloc(2);
    strcpy(s, "0");
    for (mask -= mask / 2; mask; mask >>= 1) {
        for (a = (num & mask) != 0, b = c; b;) {
            d = ((s[--b] - '0') << 1) + a;
            s[b] = "0123456789"[d % 10];
            a = d / 10;
        }
        for (; a; s = realloc(s, ++c + 1), memmove(s + 1, s, c), *s = "0123456789"[a % 10], a /= 10);
    }
    return s;
}

int main(void) {
    __uint128_t n = from_string_128_bits("10000000000000000000000000000000000001");
    n *= 7;
    char *s = to_string_128_bits(n);
    puts(s);
    free(s); // string must be freed
    // print 70000000000000000000000000000000000007
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AnatolyS
Solution 2
Solution 3 Michel