Problem with big numbers in C - c

why should a code like this should provide a so high result when I give it the number 4293974227 (or higher)
int main (int argc, char *argv[])
{
unsigned long long int i;
unsigned long long int z = atoi(argv[1]);
unsigned long long int tmp1 = z;
unsigned long long int *numbers = malloc (sizeof (unsigned long long int) * 1000);
for (i=0; tmp1<=tmp1+1000; i++, tmp1++) {
numbers[i] = tmp1;
printf("\n%llu - %llu", numbers[i], tmp1);
}
}
Result should start with the provided number but starts like this:
18446744073708558547 - 18446744073708558547
18446744073708558548 - 18446744073708558548
18446744073708558549 - 18446744073708558549
18446744073708558550 - 18446744073708558550
18446744073708558551 - 18446744073708558551
ecc...
What's this crap??
Thanks!

atoi() returns int. If you need larger numbers, try strtol(), strtoll(), or their relatives.

atoi() returns (int), and can't deal with (long long). Try atoll(), or failing that atol() (the former is preferred).

You are printing signed integers as unsigned.

Related

What exactly happens when we cast a number to a smaller size number in C?

Suppose I have something like this:
unsigned int x = (unsigned int)SomeLong;
What exactly happens if SomeLong doesn't fit in 4 bytes? What does the new memory layout look like? How exactly does casting a number to a smaller size number in C work? What happens?
It truncates the memory. This is shown by this program, which shows the binary representation of the long, and then the binary representation of the long cast to a smaller int:
#include <stdio.h>
void Print8Byte(unsigned long Value) {
for (unsigned char i = 0; i < 64; i++) {
union {
unsigned long Value;
unsigned First:1;
} Cast = {.Value = Value>>i};
putchar('0'+Cast.First);
}
putchar('\n');
}
int main(int argc, char *argv[]) {
unsigned long Num = 0x284884848; //Arbitrary Value
Print8Byte(Num);
Print8Byte((unsigned int)Num);
}
Result:
0001001000010010000100010010000101000000000000000000000000000000
0001001000010010000100010010000100000000000000000000000000000000

Casting Long to Unsigned Short Int / Strtol

There is no compile error. However, the results are not expected. My suspicion is that the casting long to unsigned short int is causing the error. How can I safely cast long to a short for Hex?
[Requiriments: Convert a row of string (which has numbers) to unsigned short int] Thanks!
unsigned short int str_to_bin (char* instr_bin_str) {
unsigned short int i = 0;
long j;
char* ptr;
j = strtol (instr_bin_str, &ptr, 10);
if (j == 0) {
fprintf (stderr, "error6: str_to_bin() failed");
return 6;
}
i = (unsigned short) j;
printf("State: 0x%X \n", i);
return i;
}
The string you're passing in is the binary representation of a number. However, when you're calling strtol you pass in 10 for the third parameter, which means it expects a string in decimal representation.
If you're expecting binary, you need to tell strtol to expect that:
j = strtol (instr_bin_str, &ptr, 2);

string to long, not giving me the correct answer

I am trying to convert number stored in the c string to long int. But I am not getting the expected output:
char str[] = "987654321012345";
long int num ;
num = 0;
//num = atol(str);
num = strtol(str, (char **) NULL, 10);
printf("%ld", num);
Output : 821493369
gcc version 4.4.7 20120313 (Red Hat 4.4.7-16)
Can you please advise what am I doing wrong here? Thanks.
In addition to using long long, you can use exact width types from stdint.h. For instance, to guarantee and 64-bit signed number you can use the int64_t type. Regardless what you do, do not cast NULL to char ** and always validate your conversions. E.g.,
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main (void) {
char str[] = "987654321012345";
long num = 0;
errno = 0;
num = strtol (str, NULL, 10);
if (errno) { /* validate strtol conversion */
perror ("strtol conversion failed.");
return 1;
}
printf ("%ld\n", num);
return 0;
}
Example Use/Output
$ ./bin/strtoltst
987654321012345
There are additional error checks you can do on the conversion, but at minimum, make sure errno is not set following your call to strtol or strtoll.
If you would like to use the guaranteed width types, then you can make the following changes:
...
#include <stdint.h>
...
int64_t num = 0;
...
num = strtoll (str, NULL, 10);
The result is the same.
I could reproduce and fix.
Code reproducing the problem
#include <stdio.h>
//#include <stdlib.h>
int main()
{
char str[] = "987654321012345";
long int num ;
char *ix;
num = 0;
//num = atol(str);
num = strtol(str, &ix, 10);
printf("%ld\n", num);
printf("%lu\n", sizeof(long));
return 0;
}
Gives as expected:
821493369
8
After a compilation warning
warning: implicit declaration of strtoll
Reason: as strtoll is undeclared, it is assumed to return an int, so the long value is first truncate to an int and than promoted back to a long.
Fix: just uncomment the #include <stdlib.h> line...
Conclusion: warnings are not meant to be ignored!
You should use long long as datatype for your number.
char str[] = "987654321012345";
long long num = strtoll(str, (char **)NULL, 10);
printf("%lld", num);
According to the C data type:
Long signed integer type. Capable of containing at least the [−2,147,483,647, +2,147,483,647] range; thus, it is at least 32 bits in size.
Long unsigned integer type. Capable of containing at least the [0, 4,294,967,295] range;
Is not enough, so you need a long long or unsigned long long and use %lli or %llu
"987654321012345" is too large.
Strol is outputing long type variable.
Long value is –2,147,483,648 to 2,147,483,647.
try
char str[] = "987654321012345";
char *pEnd;
long long num;
num = 0;
num = strtoull(str,&pEnd, 10);
printf("%lld", num);
return 0;
long long instead of long
strtoull instead of strtol
%lld instead of %ld

Why am i not able to print 47th fibonacci number correctly?

I am using 64 bit operating system ,then also i am not able to print 46th fibonacci number correctly which is less than 4 billion.
#include<cs50.h>
#include<stdio.h>
int main(void)
{
unsigned int n=50;
int array[n];
array[0]=0;
array[1]=1;
printf("%i\n",array[0]);
printf("%i\n",array[1]);
for(int i=2;i<n;i++)
{
array[i]=array[i-1]+array[i-2];
printf("%i\n",array[i]);
}
You have to use long long as your data type of the array. because You are going to store out-range numbers of the integer range.(-2,147,483,648 to 2,147,483,647)
And declaration of int i should be before the for loop.
#include<stdio.h>
int main(void)
{
int n=50;
long long array[n];
array[0]=0;
array[1]=1;
printf("%lli\n",array[0]);
printf("%lli\n",array[1]);
int i;
for(i=2;i<n;i++)
{
array[i]=array[i-1]+array[i-2];
printf("%lli\n",array[i]);
}
}
i am not able to print 46th fibonacci number correctly which is less than 4 billion.
You are most probably going out of range of an integer, which is from -4294967296 to 4294967295.
Change int array[n]; to long long array[n];
Also, the printf's should be changed from %i to %lli
Edit : On running the numbers, you get expected value of F(48) as 4807526976 which is out of range of an integer.
Using Rishikesh Raje's counting system (i.e. 1st Fibonacci is 1) where F(48) is 4807526976, then you weren't able to get F(47) 2971215073 because, as #kaylum commented, you used a signed integer array to hold your values which you need to change to unsigned, and well as change your printf statement to print an unsigned. This would allow you to reach the limit of 32 bit arithmetic:
#include <stdio.h>
#define LIMIT (50)
int main(void) {
unsigned int array[LIMIT] = {0, 1};
printf("%u\n", array[0]);
printf("%u\n", array[1]);
for (size_t i = 2; i < LIMIT; i++)
{
array[i] = array[i - 1] + array[i - 2];
printf("%u\n", array[i]);
}
return 0;
}
To get beyond 32 bits, you can switch to long, or long longs as Rishikesh Raje suggests, but work with unsigned variants if you want to reach the maximum result you can with a given number of bits.
Either Use an unsigned integer array or for more higher values use unsigned long long long array but you don't need an array to print fibonacci series you can simply do this:-
void main()
{
unsigned long long i=1, num1=1, num2=0;
printf("1 \n");
for(i; i<100 ; i++)
{
num1=num1+num2;
num2=num1-num2;
printf("%lli \n", num1);
}
getch();
}

weird output without typecasting

I was trying to execute this code through gcc compiler:
#include <stdio.h>
int main()
{
unsigned long long int x;
x = 75000 * 75000;
printf ("%llu\n", x);
return 0;
}
But it gave wrong output.
I then tried this:
#include <stdio.h>
int main()
{
unsigned long long int x;
x = (unsigned long long)75000 * (unsigned long long)75000;
printf ("%llu\n", x);
return 0;
}
And it gave correct output !
Why is this so?
The expression 75000 * 75000 is the multiplication of two integer constants. The result of this expression is also an integer and can overflow. The result is then assigned to an unsigned long long, but it has already overflowed so the result is wrong.
To write unsigned long long constants use the ULL suffix.
x = 75000ULL * 75000ULL;
Now the multiplication will not overflow.

Resources