long long multiplication in C gives wrong result - c

My C code seems to be malfunctioning and incapable of multiplying long long numbers and outputting the result, and I can't for the life of me figure out why.
Here's the culprit code:
#include "stdio.h"
int main()
{
unsigned long long primes[] = {199453LL, 200723LL, 203317LL, 205103LL, 206603LL, 208057LL, 210323LL, 210961LL, 212827LL, 214237LL, 215693LL, 216319LL};
unsigned long long numbers[6];
int i;
printf("Calculating the numbers to factor!\n");
printf("Size of long: %i\n", sizeof(long));
printf("Size of long long: %i\n", sizeof(long long));
for (i = 0; i < 6; i++)
{
numbers[i] = primes[i]*primes[11-i];
printf("%ld*%ld = %ld\n", primes[i], primes[11-i], numbers[i]);
printf("Result is %ld\n",numbers[i]);
}
return 0;
}
And here's the output when I compile this and run it (I'm using gcc version 4.8.2 on Linux)
Calculating the numbers to factor!
Size of long: 4
Size of long long: 8
199453*0 = 216319
Result is 195800547
200723*0 = 215693
Result is 344873079
203317*0 = 214237
Result is 608351169
205103*0 = 212827
Result is 701783221
206603*0 = 210961
Result is 635502523
208057*0 = 210323
Result is 809499451

Your printf format string is wrong. %ld requires a long int, %lld is for a long long int, and since you are using unsigned long long, you should use %llu, otherwise large positive values will be displayed as negative.
And, as noticed by Grzegorz Szpetkowski, the size_t (sizeof) requires %zu.
From printf(3):
l (ell) A following integer conversion corresponds to a long int or unsigned long int argument, or a following n conversion
corresponds to a pointer to a long int argument, or a following c conversion corresponds to a wint_t argument, or a following s conversion corresponds to a pointer to wchar_t argument.
ll (ell-ell). A following integer conversion corresponds to a long long int or unsigned long long int argument, or a following
n conversion corresponds to a pointer to a
long long int argument.
...
z A following integer conversion corresponds to a size_t or ssize_t argument. (Linux libc5 has Z with this meaning. Don't use it.)
Now, for example this output
199453*0 = 216319
Occurs because the little-endian 64-bit numbers 199453, 216319 and 43145473507 are correctly pushed onto the stack; but printf expects to find only 32-bit numbers on the stack, so it prints 199453, 0 (which are the top 4 bytes of 64-bit number 199453), and 216319.

Related

Unable to calculate factorial , getting output as 0 in C

Tried calculating factorial of 65, got correct output. Anything greater than 65 results in output of 0. Shocking since I'm using unsigned long int. What is amiss ?
Code:
#include <stdio.h>
void factorial(int unsigned long);
int main()
{
int unsigned long num, result;
printf("\nEnter number to obtain factorial : ");
scanf("%ld", &num);
factorial(num);
}
void factorial (int unsigned long x)
{
register int unsigned long f = 1;
register int unsigned long i;
for (i=x;i>=1;i--)
f= f*i;
printf("\nFactorial of %lu = %lu\n",x,f);
}
You certainly did not get the correct result for 65! log2(65!) is just over 302 bits (Google it), so you'd need a long int of at least 303 bits to calculate that correctly. There is no computer in the world where long int is over 300 bits (let's see how this answer ages!).
The largest factorial you can compute in 64 bits is 20! (which is about 2.4e18).
Adding on to #JohnZwinck, the maximum value for a variable of type unsigned long long (ULLONG_MAX) is 18446744073709551615. So all the values greater than 20! are going to have a garbage value
You can refer to this for more information.

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;
}

Unexpected unsigned integer behavior

I encountered this unexpected output with the following code in which I was verifying the maximum values (represented in decimal form) of the unsigned forms of short and int types when all their bits were set to 1.
#include <stdio.h>
int main()
{
unsigned int n1 = 0xFFFFFFFF;
unsigned short n2 = 0xFFFF;
printf("\nMax int = %+d", n1);
printf("\nMax short = %+d", n2);
return 0;
}
The output I get is (compiled using the Visual Studio 2017 C/C++ Compiler):
Max int = -1
Max short = +65535
Along the lines of unsigned short, I was expecting the maximum value of the unsigned int to be +4294967295. Why isn't it so?
You need to use %u for the format specifier for an unsigned type.
Using printf(), your conversions in the format string must match the type of the arguments, otherwise the behavior is undefined. %d is for int.
Try this for the maximum values:
#include <stdio.h>
int main()
{
printf("Max unsigned int = %u\n", (unsigned)-1);
printf("Max unsigned short = %hu\n", (unsigned short)-1);
return 0;
}
Side notes:
the maximum value of any unsigned type is -1 cast to that type.
Put newline at the end of your lines. Among other reasons, this flushes stdouts buffer with the default setting of line buffered.

pow() function weird behavior when used in brackets and with long long integer

I found something weird.
This function puts a digit in a number at the given spot and returns the modified number.
Now we want to do put_digit(123456789123456784, 0, 9);
That will put 9 at the end of the number, replacing the last number (4).
This is the code that WORKS:
long long int put_digit(long long int number, char place, char digit)
{
long long int result = number;
long long int power = number;
power = pow(10, (place));
result -= get_digit(number, place)*power;
result += digit*pow(10, (place));
return result;
}
The code returns 123456789123456789
This is the code that DOES NOT WORK:
long long int put_digit(long long int number, char place, char digit)
{
long long int result = number;
result -= get_digit(number, place)*pow(10, (place));
result += digit*pow(10, (place));
return result;
}
This code returns 123456789123456800 as the result.
The functions get_digit() returns the digit from the number in the given place.
This is it's code:
char get_digit(long long int number, char place)
{
long long int target = number;
char digit = 0;
target /= pow(10, place);
digit = target % 10;
return digit;
}
• This does not happen with lower numbers.
• get_digit() always returns the correct value (4 in this case).
• get_digit() is a char because this is not a counter function, and thus it is better to focus on using less memory rather than using a faster variable like int.
• I've tried using brackets to avoid troublesome operator precedence, but to no avail.
• A weird behavior is also observed when doing put_digit(123456789123456000, 2, 7), which for some reason returns 123456789123456704. This is solved by replacing the pow function in the second result calculation with the variable "power".
I just don't understand why this is happening.
Am I getting some kind of an overflow? Is it my system's fault or my own? Am I using pow() in a bad way?
The declaration of pow() is: double pow( double base, double exponent );
In the first case:
long long int power = number;
power = pow(10, (place));
the value returned by pow() is converted to long long int when it is assigned power. The rest of the computation is processed using integer numbers and the result is the one you expect.
On the second case:
result -= get_digit(number, place)*pow(10, (place));
the value returned by get_digit(number, place) is converted to double because it needs to be multiplied with a floating point number (returned by pow()). Also, the value of result is converted to double before subtracting the result of the multiplication. In the end, the computed value is converted from double to long long int to be stored in result.
But starting on some magnitude, the floating point numbers lose the precision of their least significant digit(s).
Try this simple piece of code to see for yourself:
long long int i = 123456789123456785;
for (; i <= 123456789123456795; i ++) {
printf("long long int: %lld; double: %f\n", i, (double)i);
}
It outputs:
long long int: 123456789123456785; double: 123456789123456784.000000
long long int: 123456789123456786; double: 123456789123456784.000000
long long int: 123456789123456787; double: 123456789123456784.000000
long long int: 123456789123456788; double: 123456789123456784.000000
long long int: 123456789123456789; double: 123456789123456784.000000
long long int: 123456789123456790; double: 123456789123456784.000000
long long int: 123456789123456791; double: 123456789123456784.000000
long long int: 123456789123456792; double: 123456789123456800.000000
long long int: 123456789123456793; double: 123456789123456800.000000
long long int: 123456789123456794; double: 123456789123456800.000000
long long int: 123456789123456795; double: 123456789123456800.000000
This behaviour is not a bug but a limitation of the floating point numbers.
The solution for your code is to convert the value returned by pow(10, place) to long long int as soon as it returns:
result -= get_digit(number, place)*(long long int)pow(10, place);

How do you format an unsigned long long int using printf?

#include <stdio.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Output:
My number is 8 bytes wide and its value is 285212672l. A normal number is 0.
I assume this unexpected result is from printing the unsigned long long int. How do you printf() an unsigned long long int?
Use the ll (el-el) long-long modifier with the u (unsigned) conversion. (Works in windows, GNU).
printf("%llu", 285212672);
%d--> for int
%u--> for unsigned int
%ld--> for long int or long
%lu--> for unsigned long int or long unsigned int or unsigned long
%lld--> for long long int or long long
%llu--> for unsigned long long int or unsigned long long
You may want to try using the inttypes.h library that gives you types such as
int32_t, int64_t, uint64_t etc.
You can then use its macros such as:
#include <inttypes.h>
uint64_t x;
uint32_t y;
printf("x: %"PRIu64", y: %"PRIu32"\n", x, y);
This is "guaranteed" to not give you the same trouble as long, unsigned long long etc, since you don't have to guess how many bits are in each data type.
For long long (or __int64) using MSVS, you should use %I64d:
__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b); //I is capital i
That is because %llu doesn't work properly under Windows and %d can't handle 64 bit integers. I suggest using PRIu64 instead and you'll find it's portable to Linux as well.
Try this instead:
#include <stdio.h>
#include <inttypes.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
/* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Output
My number is 8 bytes wide and its value is 285212672. A normal number is 5.
In Linux it is %llu and in Windows it is %I64u
Although I have found it doesn't work in Windows 2000, there seems to be a bug there!
Compile it as x64 with VS2005:
%llu works well.
How do you format an unsigned long long int using printf?
Since C99 use an "ll" (ell-ell) before the conversion specifiers o,u,x,X.
In addition to base 10 options in many answers, there are base 16 and base 8 options:
Choices include
unsigned long long num = 285212672;
printf("Base 10: %llu\n", num);
num += 0xFFF; // For more interesting hex/octal output.
printf("Base 16: %llX\n", num); // Use uppercase A-F
printf("Base 16: %llx\n", num); // Use lowercase a-f
printf("Base 8: %llo\n", num);
puts("or 0x,0X prefix");
printf("Base 16: %#llX %#llX\n", num, 0ull); // When non-zero, print leading 0X
printf("Base 16: %#llx %#llx\n", num, 0ull); // When non-zero, print leading 0x
printf("Base 16: 0x%llX\n", num); // My hex fave: lower case prefix, with A-F
Output
Base 10: 285212672
Base 16: 11000FFF
Base 16: 11000fff
Base 8: 2100007777
or 0x,0X prefix
Base 16: 0X11000FFF 0
Base 16: 0x11000fff 0
Base 16: 0x11000FFF
Apparently no one has come up with a multi-platform* solution for over a decade since [the] year 2008, so I shall append mine 😛. Plz upvote. (Joking. I don’t care.)
Solution: lltoa()
How to use:
#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));
OP’s example:
#include <stdio.h>
#include <stdlib.h> /* lltoa() */
int main() {
unsigned long long int num = 285212672; // fits in 29 bits
char dummy[255];
int normalInt = 5;
printf("My number is %d bytes wide and its value is %s. "
"A normal number is %d.\n",
sizeof(num), lltoa(num, dummy, 10), normalInt);
return 0;
}
Unlike the %lld print format string, this one works for me under 32-bit GCC on Windows.
*) Well, almost multi-platform. In MSVC, you apparently need _ui64toa() instead of lltoa().
In addition to what people wrote years ago:
you might get this error on gcc/mingw:
main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]
printf("%llu\n", k);
Then your version of mingw does not default to c99. Add this compiler flag: -std=c99.
Non-standard things are always strange :)
for the long long portion
under GNU it's L, ll or q
and under windows I believe it's ll only
One possibility for formatting an unsigned long long is to make use of uintmax_t. This type has been available since C99 and unlike some of the other optional exact-width types found in stdint.h, uintmax_t is required by the Standard (as is its signed counterpart intmax_t).
According to the Standard, a uintmax_t type can represent any value of any unsigned integer type.
You can print a uintmax_t value using the %ju conversion specifier (and intmax_t can be printed using %jd). To print a value which is not already uintmax_t, you must first cast to uintmax_t to avoid undefined behavior:
#include <stdio.h>
#include <stdint.h>
int main(void) {
unsigned long long num = 285212672;
printf("%ju\n", (uintmax_t)num);
return 0;
}
Well, one way is to compile it as x64 with VS2008
This runs as you would expect:
int normalInt = 5;
unsigned long long int num=285212672;
printf(
"My number is %d bytes wide and its value is %ul.
A normal number is %d \n",
sizeof(num),
num,
normalInt);
For 32 bit code, we need to use the correct __int64 format specifier %I64u. So it becomes.
int normalInt = 5;
unsigned __int64 num=285212672;
printf(
"My number is %d bytes wide and its value is %I64u.
A normal number is %d",
sizeof(num),
num, normalInt);
This code works for both 32 and 64 bit VS compiler.
Hex:
printf("64bit: %llp", 0xffffffffffffffff);
Output:
64bit: FFFFFFFFFFFFFFFF

Resources