3

I have data type unsigned __int128 data; so I don't think this is a type issue, but I have no idea why it is occuring

#include <stdio.h>

int main(int argc, char *argv[]) {
    unsigned __int128 z = 1911602146;
    unsigned __int128 n = 4003562209;

    //case 1
        unsigned __int128 result = fmod((pow(z, 2)  * 2), n);
        printf("%d\n", result);

    //case 2
        unsigned __int128 result_2 = fmod(pow(z, 2), n);
        printf("%d\n", result_2);
}

returns:

-669207835 => this is the correct option and it should be 7629321670
-480306461
Kendall Weihe
  • 2,021
  • 4
  • 27
  • 53

3 Answers3

1
printf("%d\n", result);
//      ^^

%d expects an int. You're passing it an unsigned __int128 instead, resulting in undefined behavior. Most likely, printf is taking part of the representation of result and interpreting it as an int.

I don't know what the right format specifier would be, but you should find the right one and use it. Also, you shouldn't be using floating-point functions on your data; you're losing precision there.

user2357112
  • 260,549
  • 28
  • 431
  • 505
0

First of all, __int128 is a GNU CC extension, and thus there's no portable way to handle them, neither a portable way to print them.

As it happens to be, there's (ironically...) no support, not even from Glibc, for printfing(), __int128s nor unsigned __int128s.

The only alternative you have is to write your own functions to print them out in decimal, or better yet, in hexadecimal, because this kind of large integers can get pretty unreadable in decimal too easily.

BTW, this is undefined behaviour:

printf("%d\n", result);

Because the "%d" specifier expects an int as argument, nothing less, nothing more, nothing else.

I hope this has led some light on you!

3442
  • 8,248
  • 2
  • 19
  • 41
0

First avoid the floating-point trip during the calculation.
Then, only for printing, convert the result (which is < 10^10) to double in order to use the printf function

unsigned __int128 z = 1911602146;
unsigned __int128 n = 4003562209;

unsigned __int128 result = (z * z * 2) % n;
printf("%.0lf\n", (double)result);

unsigned __int128 result_2 = (z * z) % n;
printf("%.0lf\n", (double)result_2);

That should give you

3625759213
3814660711

(you cannot get 7629321670 anyway as a result, since it is bigger than the modulo operand, 'n')

Déjà vu
  • 28,223
  • 6
  • 72
  • 100