Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8728739
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 13, 20262026-06-13T08:42:25+00:00 2026-06-13T08:42:25+00:00

Im trying to convert my arbitrary precision integer class to be able to use

  • 0

Im trying to convert my arbitrary precision integer class to be able to use digits that are not just 8 bits per digit. Ive stumbled upon a weird problem: I am able to use uint16_t
for my base digit type, but not uint32_t. My code will return bad results. The example I used to find what was going wrong is 0x1111111111111111 * 0x1111111111111111, which should be0x123456789abcdf00fedcba987654321. However, I am getting 0x123456789abcdf0fedcba987654321.

I thought that I had changed all of the hardcoded types so that changing the base digit type would not matter, but apparently not.

Here is the relevant code:

typedef uint32_t                          digit;            // original code uses uint8_t; uint16_t works too
typedef uint64_t                          double_digit;     // int type to hold overflow values

typedef std::deque <digit>                base;

const digit NEG1 = -1;                    // uint8_t -> 255, uint32_t -> 4294967295
const digit BITS = sizeof(digit) << 3;    // sizeof gives the number of bytes, so multiply that by 8 to get the number of bits
const digit HIGH_BIT = 1 << (BITS - 1);   // uint8_t -> 128

        // left bit shift. sign is maintained
        integer operator<<(uint64_t shift){
            if (!*this || !shift)
                return *this;
            base out = digits;
            for(uint64_t i = 0; i < (shift / BITS); i++)
                out.push_back(0);
            shift %= BITS;
            if (shift){
                out.push_back(0);
                return integer(out, _sign) >> (BITS - shift);
            }
            return integer(out, _sign);
        }

        // right bit shift. sign is maintained
        integer operator>>(uint64_t shift){
            if (shift >= bits())
                return integer(0);
            base out = digits;
            for(uint64_t i = 0; i < (shift / BITS); i++)
                out.pop_back();
            shift %= BITS;
            if (shift){
                base v;
                for(d_size i = out.size() - 1; i != 0; i--)
                    v.push_front(((out[i] >> shift) | (out[i - 1] << (BITS - shift))) & NEG1);
                v.push_front(out[0] >> shift);
                out = v;
            }
            return integer(out, _sign);
        }

        // operator+ calls this
        integer add(integer & lhs, integer & rhs){
            base out;
            base::reverse_iterator i = lhs.digits.rbegin(), j = rhs.digits.rbegin();
            bool carry = false;
            double_digit sum;
            for(; ((i != lhs.digits.rend()) && (j != rhs.digits.rend())); i++, j++){
                sum = *i + *j + carry;
                out.push_front(sum);
                carry = (sum > NEG1);
            }
            for(; i != lhs.digits.rend(); i++){
                sum = *i + carry;
                out.push_front(sum);
                carry = (sum > NEG1);
            }
            for(; j != rhs.digits.rend(); j++){
                sum = *j + carry;
                out.push_front(sum);
                carry = (sum > NEG1);
            }
            if (carry)
                out.push_front(1);
            return integer(out);
        }

        // operator* calls this
        // Long multiplication
        integer long_mult(integer & lhs, integer & rhs){
            unsigned int zeros = 0;
            integer row, out = 0;
            for(base::reverse_iterator i = lhs.digits.rbegin(); i != lhs.digits.rend(); i++){
                row.digits = base(zeros++, 0); // zeros on the right hand side
                digit carry = 0;
                for(base::reverse_iterator j = rhs.digits.rbegin(); j != rhs.digits.rend(); j++){
                    double_digit prod = (double_digit(*i) * double_digit(*j)) + carry;// multiply through
                    row.digits.push_front(prod & NEG1);
                    carry = prod >> BITS;
                }
                if (carry)
                    row.digits.push_front(carry);
                out = add(out, row);
            }
            return out;
        }

Is there something obvious that I missed that might cause incorrect calculations? I have stared at this code for a little too long in one burst.

The full modified code is here.

EDIT: I have tested the code on ideone, and it is returning the correct value for this calculation, but my computer still does not. Is there any good explanation for this?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-13T08:42:26+00:00Added an answer on June 13, 2026 at 8:42 am

    The problem appears to be due to unintended excessive right-shifting. You mention that your ideone post doesn’t reproduce the problem. While testing, I noticed that in your ideone post, the type of digit was actually still set to 16-bit. The moment I changed this to 32 bit (to reflect the SO code snippet) and tried to compile under gcc, I got a bunch of warnings about excessive right shift. Running the program resulted in an infinite loop, which, combined with the right-shift warnings and the fact that you get different behavior on your platform strongly suggests undefined behavior is occurring.

    More specifically, there are places where you’re getting bit-size mismatches between int types (ie, you still have a few chunks of code to update).

    The trouble maker appears to be setFromZ. Here you have the integer type specified by Z, and the integer type specified by base::value_type. The two are not guaranteed to have the same number of bits, so the bit-shift and bit-mask code in that function are not working correctly when a bit mismatch occurs. And a mismatch is occurring for several instantiations of that template that occur in your ideone code, when uint32_t is the digit type (at least in my environment).

    Edit: Confirmation that excessive right-shift is undefined according to standard: Reference: SO Post, see accepted answer, which quotes the standard.

    (C++98 §5.8/1) states that:
    The behavior is
    undefined if the right operand is negative, or greater than or equal
    to the length in bits of the promoted left operand.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to find the n th digit of an integer of an arbitrary
Trying to convert output from a rest_client GET to the characters that are represented
When trying to convert date/time from string to DateTime, I'm not getting the correct
I'm trying to write a function that converts a base 10 integer to a
Trying to convert a string to NSURL and this is not happening. barcodeTextLabel.text =
I am trying to figure out how to convert an arbitrary array or collection
I am trying to write a function that converts between Maps with integer keys
I am trying convert the following Collatz Conjecture algorithm from: public class CollatzConjexture {
I am trying convert the following Collatz Conjecture algorithm from: public class CollatzConjexture {
I´m trying to convert that: <% var obj = Model.Div; %> <script type=text/javascript> var

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.