miscalculation with long long integers - c

In last iteration of the loop result is wrong. I know that before subtraction numbers can be bigger than long. That is why I set power to long long. Result in last iteration should be 17888888888888888889. Why it is not?
const int NR_LEVELS = 18;
unsigned long levels[NR_LEVELS];
unsigned long long power = 10;
for(unsigned int i = 0; i < NR_LEVELS; i++) {
levels[i] = ((i+1)*10*power-(i+2)*power+1)/9;
cout << levels[i] << endl;
power *= 10;
}
levels[17] = 17888888888888888889lu;
for(unsigned int i = 0; i < NR_LEVELS; i++) {
cout << levels[i] << endl;
}

The intermediate value (before dividing by 9) overflows 64-bit integer. That is the reason why you don't get the expected result.
To be more precise, the maximum value of 64-bit integer is:
18446744073709551615
Compared to the (smallest) intermediate value before division:
161000000000000000001
This answer is assuming that long type in your code translate to a 64-bit integral type (the standard mandates that long type is at least 32-bit, so you might also get 32-bit integral type depending on the environment). Depending on the OS, computer architecture and the compiler, the upper limit of long type may vary.

Related

Calculating max long value using exponent overflows

I'm trying to figure out maximum value for type long by calculating an exponential of base 2 to the power of the bit number.
Unfortunately the calculation overflows at step 61 and I don't understand why.
long exponential(int base, int exponent)
{
long result = (long)base;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
unsigned int sLong = sizeof(long);
long lResult = exponential(2, (sLong * 8) - 1);
lResult is 0 after running the function.
What's odd is that when I do this for char, short and int it works fine.
The code here has an off-by-one error.
Consider the following: what is the result of exponential(10, 2)? Empirical debugging (use a printf statement) shows that it's 1000. So exponential calculates the mathematical expression be+1.
The long type usually has 64 bits. This seems to be your case (seeing that the overflow happens around step 64). Seeing that it's a signed type, its range is (typically) from -263 to 263-1. That is, the maximal power of 2 that the data type can represent is 262; if the code tries to calculate 263, then overflow happens (you probably want to avoid it).
So, because of the off-by-one error, the code will cause an overflow for exponent greater or equal to 62.
To fix the off-by-one error, start multiplying from 1:
long power_of(int base, int exponent)
{
long result = (long)1; // 0th power of base is 1
for (int i=0; i<exponent;i++) {
result*=base;
}
return result;
}
However, this will not get rid of the overflow, because the long data type cannot represent the number 263. Fortunately, you can use unsigned long long, which is guaranteed to be big enough for the type of calculations you are doing:
unsigned long long power_of(int base, int exponent)
{
unsigned long long result = 1ULL; // 0th power of base is 1
for (int i=0; i<exponent;i++) {
result*=base;
}
return result;
}
Print it with the llu format:
printf("%llu", power_of(2, 63));

Iterate bits from left to right for any number

I am trying to implement Modular Exponentiation (square and multiply left to right) algorithm in c.
In order to iterate the bits from left to right, I can use masking which is explained in this link
In this example mask used is 0x80 which can work only for a number with max 8 bits.
In order to make it work for any number of bits, I need to assign mask dynamically but this makes it a bit complicated.
Is there any other solution by which it can be done.
Thanks in advance!
-------------EDIT-----------------------
long long base = 23;
long long exponent = 297;
long long mod = 327;
long long result = 1;
unsigned int mask;
for (mask = 0x80; mask != 0; mask >>= 1) {
result = (result * result) % mod; // Square
if (exponent & mask) {
result = (base * result) % mod; // Mul
}
}
As in this example, it will not work if I will use mask 0x80 but if I use 0x100 then it works fine.
Selecting the mask value at run time seems to be an overhead.
If you want to iterate over all bits, you first have to know how many bits there are in your type.
This is a surprisingly complicated matter:
sizeof gives you the number of bytes, but a byte can have more than 8 bits.
limits.h gives you CHAR_BIT to know the number of bits in a byte, but even if you multiply this by the sizeof your type, the result could still be wrong because unsigned types are allowed to contain padding bits that are not part of the number representation, while sizeof returns the storage size in bytes, which includes these padding bits.
Fortunately, this answer has an ingenious macro that can calculate the number of actual value bits based on the maximum value of the respective type:
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
The maximum value of an unsigned type is surprisingly easy to get: just cast -1 to your unsigned type.
So, all in all, your code could look like this, including the macro above:
#define UNSIGNED_BITS IMAX_BITS((unsigned)-1)
// [...]
unsigned int mask;
for (mask = 1 << (UNSIGNED_BITS-1); mask != 0; mask >>= 1) {
// [...]
}
Note that applying this complicated macro has no runtime drawback at all, it's a compile-time constant.
Your algorithm seems unnecessarily complicated: bits from the exponent can be tested from the least significant to the most significant in a way that does not depend on the integer type nor its maximum value. Here is a simple implementation that does not need any special case for any size integers:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
unsigned long long base = (argc > 1) ? strtoull(argv[1], NULL, 0) : 23;
unsigned long long exponent = (argc > 2) ? strtoull(argv[2], NULL, 0) : 297;
unsigned long long mod = (argc > 3) ? strtoull(argv[3], NULL, 0) : 327;
unsigned long long y = exponent;
unsigned long long x = base;
unsigned long long result = 1;
for (;;) {
if (y & 1) {
result = result * x % mod;
}
if ((y >>= 1) == 0)
break;
x = x * x % mod;
}
printf("expmod(%llu, %llu, %llu) = %llu\n", base, exponent, mod, result);
return 0;
}
Without any command line arguments, it produces: expmod(23, 297, 327) = 185. You can try other numbers by passing the base, exponent and modulo as command line arguments.
EDIT:
If you must scan the bits in exponent from most significant to least significant, mask should be defined as the same type as exponent and initialized this way if the type is unsigned:
unsigned long long exponent = 297;
unsigned long long mask = 0;
mask = ~mask - (~mask >> 1);
If the type is signed, for complete portability, you must use the definition for its maximum value from <limits.h>. Note however that it would be more efficient to use the unsigned type.
long long exponent = 297;
long long mask = LLONG_MAX - (LLONG_MAX >> 1);
The loop will waste time running through all the most significant 0 bits, so a simpler loop could be used first to skip these bits:
while (mask > exponent) {
mask >>= 1;
}

Can I use CHAR_BIT as the basis for determining the number of bits in other types?

For example, does the following code make no assumptions that might be incorrect on certain systems?
// Number of bits in an unsigned long long int:
const int ULLONG_BIT = sizeof(unsigned long long int) * CHAR_BIT;
I agree with PSkocik's comment to the original question. C11 6.2.6 says CHAR_BIT * sizeof (type) yields the number of bits in the object representation of type type, but some of them may be padding bits.
I suspect that your best bet for a "no-assumptions" code is to simply check the value of ULLONG_MAX (or ~0ULL or (unsigned long long)(-1LL), which should all evaluate to the same value):
#include <limits.h>
static inline int ullong_bit(void)
{
unsigned long long m = ULLONG_MAX;
int n = 0, i = 0;
while (m) {
n += m & 1;
i ++;
m >>= 1;
}
if (n == i)
return i;
else
return i-1;
}
If the binary pattern for the value is all ones, then the number of bits an unsigned long long can hold is the same as the number of binary digits in the value.
Otherwise, the most significant bit cannot really be used, because the maximum value in binary contains zeros.

How do I mute this error : "integer literal is too large to be represented in a signed integer type"

I have this school assignment in C where I will be corrected with the following flags :
-Wall -Wextra -Werror
So this harmless warning becomes an error and prevents compilation :
integer literal is too large to be represented in a signed integer type
(code still works) but if I can't mute it my work will be considered wrong
Here is my code :
static unsigned long long piece_to_map(unsigned short little)
{
static unsigned short row;
unsigned long long big;
char i;
unsigned long long mask_left;
unsigned long long mask_top;
mask_left = 9259542123273814144;
mask_top = 18374686479671623680;
row = 15;
big = 0;
i = 0;
while (i < 16)
{
big |= (little & (row << i)) << i;
i += 4;
}
while ((big & mask_t) == 0)
big = big << 8;
while ((big & mask_l) == 0)
big = big << 1;
return (big);
}
What I'm trying to achieve here is to transform an unsigned short (representing a shape in a 4x4 square) to an unsigned long long representing the same shape in a 8x8 square having the shape cornered top-left. It works perfectly and according to my expectations, I just need to avoid having the warning. I was formerly using the (normally equivalent) binary expression instead and didn't get any warning
0b1111111100000000000000000000000000000000000000000000000000000000
and
0b1000000010000000100000001000000010000000100000001000000010000000
The problem is that the 0bxxxx form is not standard C (As I read in this StackOverflow answer), therefore I am not allowed to use it.
I also tried
mask_left = (unsigned long long)9259542123273814144;
mask_top = (unsigned long long)18374686479671623680;
The compiler still tells me that the value is too large to be represened in a signed integer type. What am I doing wrong ? Is there any way to fix this at all ?
Implicitly, the integer literal is signed and of course the values are too big for a signed long long, so you need to let the compiler know that they have type unsigned, like this
mask_left = 9259542123273814143U;
mask_top = 18374686479671623680U;
Rewrite it with explicit size:
mask_left = 9259542123273814144uLL;
mask_top = 18374686479671623680uLL;
By writing it as (unsigned long long) 9259542123273814144 it means to take the integer and then cast it longer. Unfortunately, the integer is probably munged (by throwing away the higher bits to make it an int) and then increasing the size.
Signed integer literals cannot be larger than 2147483648. For a number larger than that, you need to add the LL prefix, which tells the compiler it is a long long. In your case, you want ULL as that designates an unsigned long long, which is what you're assigning to.

Issue with long long calculation

I have code that loops through numbers and creates the character array representation of that integer. So for a number like 1234 I get an array that looks like {'1', '2', '3', '4'}
Part of the code is shown below:
do {
//print here
c[i++] = (char)(((int)'0')+(num - (num/10)*10 ));
} while ((num = num/10) != 0);
I am having an issue when it comes to large data types like long long int: 18446612134627563776
I printed the values in the loop are:
18446612134627563776
18446730879801352832
18446742754318731738
...
18446744073709551615
The values should be
18446612134627563776
1844661213462756377
184466121346275637
...
18
1
The strange thing is that the loop terminates. The last printed value is 18446744073709551615 != 0, so not sure why it terminated there. I think its some issue with the data type that i am not doing right.
This is the print statement:
printk("long=%llu sec=%llu , char=%c\n", num, (num/10)*10, (char)(((int)'0')+((num - (num/10)*10 ))));
Your code is fine. The problem is that the type of num is signed (i.e. just long long). Change it to (unsigned long long) and you should be good to go.
long long int: 18446612134627563776
long long int is a signed type, usually 64 bits wide, with the maximal representable number
2^63-1 = 9223372036854775807
Your value is larger than that, and overflows, probably to
2^63 - 18446612134627563776 = -131939081987840
The printed values are
2^64 + (-131939081987840)/(10^k)
Change the type to unsigned long long to get the expected results.
Why don't you use the modulo operator to compute the remainder of the division to obtain the last digit?
integer below
do {
c[i++] = (char)(((int)'0')+(num %10 ));
} while ((num = (num/10)) != 0);
It isnt that it overflows, Ive tested it with this code.
unsigned long long num = 18446612134627563776;
char c[100];
unsigned int i = 0;
do {
//print here
c[i++] = '0'+ (char)(num - (num/10)*10 );
} while ((num = num/10) != 0);
c[i] = '\0';
cout << c << endl;
The problem is that the compiler is probably trying to use 10 as an int, and is having problems converting. After putting the casting in, it actually works. Problem is that the algorithm is backwards as it will bring in the 6, then the 7, etc... The output is as follows from the above code which is exactly the same as his with the exception of the casting.
This is actual code, and actual output.
677365726431221664481
Hope this helps :-)

Resources