-2

This may have been asked already, but I was unable to find it on this forum. I had a general question about integer arithmetic in c++ when doing arithmetic on large integers.

unsigned int value = 500000;
value = (value * value) % 99;

The correct value to the above code would be 25, however when this is implemented in C++ I get a value of 90.

I looked at the disassembly and that gave me a slight idea as to why it may be coming back with an erroneous value, the disassembly is as follows

    unsigned int value = 500000;
    00D760B5  mov         dword ptr [value],7A120h  

    value = ((value * value) % 99);
    00D760BC  mov         eax,dword ptr [value]  
    00D760BF  imul        eax,dword ptr [value]  
    00D760C3  xor         edx,edx  
    00D760C5  mov         ecx,63h  
    00D760CA  div         eax,ecx  
    00D760CC  mov         dword ptr [value],edx  

It appears to be placing it into a 32 bit register, and that is why the result is coming back erroneous.

Nevertheless, my question is how can I mimic the language to give me the correct answer? I'm sure there's an easy and straightforward way to do it but I'm drawing a blank.

Feek
  • 297
  • 3
  • 15
  • Have you tried `unsigned long int` or even `unsigned long long int`? – ForceBru Feb 27 '17 at 04:57
  • Yes, these would work for this example, but this is a small-scale implementation of my whole code. I just want to know why this doesn't work, because I feel it should. – Feek Feb 27 '17 at 04:58
  • 1
    `value * value` is equal to 250'000'000'000. This wouldn't even fit into `unsigned long` as shown [here](http://www.cplusplus.com/reference/climits/). – ForceBru Feb 27 '17 at 05:04
  • But why is it trying to fit the result into the unsigned int prior to performing modulus on it? Shouldn't it take 250,000,000,000 mod it by 99 and then store that into the unsigned int? – Feek Feb 27 '17 at 05:06
  • 2
    where do you expect that huge number be put before calculating the modulus? – ForceBru Feb 27 '17 at 05:09
  • Use [boost::multiprecison](http://www.boost.org/doc/libs/1_63_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html) – PaulMcKenzie Feb 27 '17 at 05:21

2 Answers2

3

You should consider using a larger integer type, such as unsigned long or unsigned long long. On my machine both of these give you eight bytes of working space, which allows for a maximum value of 18,446,744,073,709,551,615. This is comfortably large enough to fit 500000^2=250,000,000,000.

But, in my opinion, that's a poor solution. You should, instead, use better mathematics. The follow modular identity should let you do what you want:

(ab) mod n = [(a mod n)(b mod n)] mod n.

In you case, you'd write:

unsigned int value = 500000;
value = ((value%99)*(value%99))%99;
Richard
  • 56,349
  • 34
  • 180
  • 251
0

The numbers you are working with that are really big. It some other languages like python they have built in libraries that handle really big numbers in special ways because a single 32-bit integer cant hold that much. C++ does not do that, and as ForceBru put, the result is gigantic and is giving your overflow errors.

If you want to deal with long numbers you could manipulate polynomials in coefficient representation for big integers, or look for a scientific computing library online.

Garrigan Stafford
  • 1,331
  • 9
  • 20