Multiplication and Division unsigned integers - c

In my program , I have to perform arithmetic operations on unsigned integers.
The variable a has a range from 0 to 4294967295.
The variable b has a range from 0 to 32.
When I check the boundary condition by taking the maximun values for a and b,I am getting 0 as the answer since overflow occurs when I try to multiply a and MAX_NS.Ideally I should get 7 as the answer.How could I write the program such that overflow is taken care of and I get 7 as the answer and hopefully it works for other valid value range for a and b.Thanks.
#include "stdio.h"
#define MAX_NS 1000000000
int main()
{
unsigned int a = 4294967295;
unsigned int b = 32 ;
unsigned int c = ((b * MAX_NS)/a);
printf("%d",c);
}
**Edit:**Please note that I can't use unsigned long long.I can use only unsigned int for the variables.

Here is solution as Weather Vane suggested
#include "stdio.h"
#define MAX_NS 1000000000
int main()
{
unsigned long long a = 4294967295;
unsigned long long b = 32;
unsigned long long c = ((b * MAX_NS) / a);
printf("%llu", c);
}

The key is that the product b * MAX_NS must be computed using wide enough math.
Make certain at least one of the * operands is unsigned long long.
With large enough b and small enough a, the quotient will need a wider type to avoid overflow;
#include "stdio.h"
// #define MAX_NS 1000000000
#define MAX_NS 1000000000LLU
int main(void) {
unsigned int a = 4294967295; // type may remain unsigned
unsigned int b = 32 ; // type may remain unsigned
unsigned long long c = ((b * MAX_NS)/a);
printf("%llu",c);
}
Alternatively, coax the multiplication gently by multiplying by 1ull. In general avoid casting as in (unsigned long long) b * MAX_NS. Rampant practice of casting surprisingly sometimes narrows the math which could happen here at a later date with uintmax_t b.
#define MAX_NS 1000000000
int main(void) {
unsigned int a = 4294967295; // type may remain unsigned
unsigned int b = 32 ; // type may remain unsigned
unsigned long long c = ((1ull * b * MAX_NS)/a);
printf("%llu",c);
}

Related

Finding modulus with very large exponentiation and divisor in C

I need a function in C that calculates a^n mod q, where the divisor q is determined to be very big (15,383,399,235,709,406,497) and the exponent n may also be as large as that.
Based on the property of modulo multiplication, that (a * b) mod n = ((a mod n) * (b mod n)) mod n, my attempt is as follows:
#include <stdio.h>
unsigned long long int modExp(unsigned long long int base, unsigned long long int expo, unsigned long long int mod)
{
unsigned long long int out = 1;
unsigned long long int cnt;
for (cnt=expo; cnt>0; cnt--)
{
out = (out * base) % mod;
}
return out;
}
int main()
{
printf("%llu", modExp(3, (189 + 50 * 223), 15383399235709406497));
return 0;
}
As seen in the main function above, I tested my function modExp with base 3, exponent (189 + 50 * 223), and divisor 15383399235709406497. It gave the output 3915400295876975163 with some warnings that
In function ‘findxA’:
findxA.c:17:32: warning: integer constant is so large that it is unsigned [enabled by default]
unsigned long long int h = 12036625823877237123;
^
findxA.c:17:5: warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
unsigned long long int h = 12036625823877237123;
^
findxA.c:18:32: warning: integer constant is so large that it is unsigned [enabled by default]
unsigned long long int q = 15383399235709406497;
^
findxA.c:18:5: warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
unsigned long long int q = 15383399235709406497;
^
findxA.c: In function ‘main’:
findxA.c:34:48: warning: integer constant is so large that it is unsigned [enabled by default]
printf("%llu", modExp(3, (189 + 50 * 223), 15383399235709406497));
^
findxA.c:34:5: warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
printf("%llu", modExp(3, (189 + 50 * 223), 15383399235709406497));
^
To verify this answer, I compared the result (given by the C function) with the output given by evaluating the expression 3^(189 + 50 * 223) `mod` 15383399235709406497, written in Haskell. This Haskell expression evaluated to a different decimal, 12349118475990906085. I think it is my C function that is wrong, since I believe Haskell does a better job at handling such large decimals.
How can I improve my C function, modExp?
Edit: I have tried the option of the first answer of this question. However, as I am trying to deal with the decimal of unsigned long long int, I have switched every input and return types from int to unsigned long long int. This resulted in a Segmentation fault.
Edit2: I have used the function described on the above link in a wrong way. It does not give Segmentation fault; but it still does not output the correct decimal.
To reduce the chance of overflow, you can rely on (x*y)%z == ((x%z) * (y%z)) % z.
For example (untested):
unsigned long long int modExp(unsigned long long int base, unsigned long long int expo, unsigned long long int mod)
{
unsigned long long int baseMod = base%mod;
unsigned long long int out = 1;
unsigned long long int cnt;
for (cnt=expo; cnt>0; cnt--)
{
out = ( (out%mod) * baseMod) % mod;
}
return out;
}
Also note that exponentiation can be done more efficiently as "product of squares". For example, x ** 5 == 1*(x**4) * 0*(x**2) * 1*(x**1) because 5 == 1*4 + 0*2 + 1*1 (or 5 == 101b).
For example (untested):
unsigned long long int modExp(unsigned long long int base, unsigned long long int expo, unsigned long long int mod)
{
unsigned long long int out = 1;
unsigned long long int temp = base%mod;
while(exp0 > 0) {
if( (exp0 & 1) != 0) {
out = (out * temp) % mod;
}
temp = (temp*temp) % mod;
exp0 >>= 1;
}
return out;
}
For large exponents this should make a huge difference in performance (e.g. if the exponent is 123456 then the loop would have 17 iterations instead of 123456 iterations).
Also; if this is for some kind of cryptography (not unlikely); then you should state that clearly because you will probably want "constant time" (to reduce the chance of timing side-channels - e.g. inferring information about the exponent from how much time modExp() takes to execute).
Finally; even with the changes, numbers up to 15,383,399,235,709,406,497 are probably too large for unsigned long long (you'd need to ensure mod * mod <= ULLONG_MAX); which means that you'll probably need to use/implement "big integer" operations (e.g. maybe a typedef struct { uint32_t digit[4]; } MY_NUMBER_TYPE thing to handle 128-bit integers, with functions for multiplication and modulo).
This will never work this way!
This result of the multiplication here alone
out = (out * base) % mod;
needs potentially more than the 64 bit of the underlying data type. And if an integer overflow occurs (ie, the most significant bits get cut off), the mod operation turns out wrong!
Use larger data types, or use a different approach :-)
If you like, btw, please use this test code to see that there is actually an integer overflow occuring TWICE with your inputs:
#include <stdio.h>
unsigned long long int modExp(unsigned long long int base, unsigned long long int expo, unsigned long long int mod)
{
unsigned long long int out = 1;
while(expo>0)
{
if(expo % 2 == 1)
out = (out * base) % mod;
expo = expo >> 1;
if (base * base < base) printf("WARNING! INTEGER OVERFLOW!!!!\n");
base = (base * base) % mod;
}
return out;
}
int main()
{
printf("%llu", modExp(3, (189 + 50 * 223), 15383399235709406497));
return 0;
}

concatenate two integers in hexa and save them in long long int C

How can I concatenate two integers and save the data in long long int,
Example:
int x=0x1234abcd;
int y=0x5678cdef;
the result is,
long long z=0x1234abcd5678cdef;
Here is the sample code
int main(void) {
int x = 0x1234abcd;
int y = 0x5678cdef;
long long z = ((long long)x<<32) | y;/* x needs to be type casted as long long */
printf("%llx\n",z);
return 0;
}
Also take consideration of x or y being negative number i.e if sign bit is set(1). It's better to declare type as unsigned as pointed by #harold.

C - How to print calculated numbers that have 15 digits?

I tried to print the result of 99,999 * 99,999 * 99,999, the result should have been 999,970,000,299,999 but what got printed instead was 18446744072244127711. I tried to print 20000 * 20000 * 20000 and the result was pretty much the same. Can you guys tell me how to get the real result?
#include <stdio.h>
int main()
{
int num;
printf("Insert number : ");
scanf("%ld", &num);
fflush(stdin);
unsigned long long int total = num * num * num;
printf("Result : %llu", total);
getchar();
return 0;
}
One way to do it is:
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main(void)
{
uint64_t x = 99999;
printf("%" PRIu64 "\n", x*x*x);
}
You may also be able to do this with unsigned long or unsigned long long types, but these depend on your C implementation (the compiler you are using).
The arithmetic you attempted overflowed the supported range of the int type you were using. When programming, it is important to ensure that the calculations you do will not overflow the range of the types you use.
Additionally, you must be careful about types in C code:
When using scanf, match the conversion specifier to the type. For example, when scanning a decimal numeral for an int object, you should use %d, not %ld. %ld is for long int.
In unsigned long long int total = num*num*num;, the unsigned long long int affects the type of total. It does not affect the type used in the calculation num*num*num. In that expression, the type of num is used. To use unsigned long long int in the calculation, you would have to convert one or all of the operands to unsigned long long int, as by using a cast: (unsigned long long int) num * num * num.
By assigning 99999 to a uint64_t object, which I named x, I ensured that x*x*x was calculated with uint64_t arithmetic. (uint64_t is a 64-bit unsigned integer.) Another way to do this would be with UINT64_C(99999) * UINT64_C(99999) * UINT64_C(99999). UINT64_C is a macro defined in stdint.h that essentially means “treat this constant as having type uint64_t or wider (actually uint_least64_t).” This could also be done with UINT64_C(99999) * 99999 * 99999 because C will automatically convert the narrower-type integer operands to the wider-type integer operand. It could also be done with (uint64_t) 99999 * 99999 * 99999.
PRIu64 is a macro that provides the right printf conversion specifier for uint64_t. It is defined in inttypes.h.
Bugs:
%ld on an int invokes undefined behavior.
fflush(stdin) invokes undefined behavior since stdin is an input stream.
num*num*num is carried out on operands that have type int, so you get overflow if you attempt 99999 * 99999 * 99999 since this is a larger number than 231-1 (assuming 32 bit int).
Fixed code:
#include <stdio.h>
int main(void)
{
int num;
printf("Insert number : ");
scanf("%d",&num); getchar();
long long int total = (long long)num*num*num;
printf("Result : %llu",total);
getchar();
return 0;
}

C - RSA Cryptosystem Decryption Issue (unsigned long long not big enough?)

I'm working on an assignment where I have to build an RSA Cryptosystem. I was able to encrypt the cipher key no problem however I'm having trouble decrypting it due to the result of the exponent being so large. I've tried using unsigned long long int but I'm still getting an output of 0.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Unsigned long long int power function
unsigned long long getPower(unsigned long long int base, int exponent){
unsigned long long result = 1;
int count = 0;
while(count != exponent){
result *= base;
count++;
}
return result;
}
int decryptFile(int cipherInt, int n, int d){
int plainInt;
unsigned long long int cipherIntLong = cipherInt;
unsigned long long int power = getPower(cipherIntLong, d);
printf("%llu\n", power);
return (int) plainInt;
}
int main(){
decryptFile(1394, 3127, 2011);
}
I should add that the professor made no mention of using a big number library so I'm sure we are most likely not supposed to use one for this assignment.
The maximum value of an unsigned 64-bit integer is 18,446,744,073,709,551,615
However, 1394^2011 is more around 1.296 x 10^6323. That is 7.02 x 10^6303 times larger than the maximum value of an unsigned 64-bit integer.
TL;DR: Use a BigInteger library, a really big one.
Seriously though, the main reason RSA can compute such large powers is because RSA operates under a modulus, so if we use Modular Exponentiation, we require far less computational power to reach the result. Calculating the result by raising the plaintext to the exponent and then applying the modulus at the end isn't computationally feasible.

How to append the letters ULL to a number you don't already know in C

I have the following code:
#include <stdio.h>
#include <stdint.h>
#define APPEND(x, y) x ## y
#define ULL(x) APPEND(x, ull)
int main (void)
{
unsigned long long int a = ULL(12345678901234567890);
printf("val: 0x%llx\n", a);
return 0;
}
It returns the hex value of a registry qword 12345678901234567890.
How do I change this as it could be any number rather than a specific one.
[Update from OP's deleted "answer"]
Do I change
unsigned long long int a = ULL(12345678901234567890);
to
unsigned long long int a = (unsigned long long)
where x will = 12345678901234567890
Sorry for sounding stupid on here.... but the value of x could be anything.
As #Felix Palmen said, ULL is for specifying of an integral literal.
Let's say if the function return that big number, you would do
unsigned long long int a = (unsigned long long) function_which_return_big_number();
But to allow this function return that big number, it already has to be unsigned long long.
Last usecase could be that these large numbers could be strings, then you would use strtoull.

Resources