Problem to return and printf unsigned long - c

I don't understand why my code is still printing int values (that are overflown) while I want unsigned long values!
There is my code :
#include <stdio.h>
unsigned long factorial(int num) {
if ((num == 0) || (num == 1 )) {
return 1;
} else if (num < 0) {
return 0;
} else {
return num * factorial(num - 1);
}
}
int main(void) {
int num;
char liste;
printf("Choisir un nombre pour trouver son factoriel : ");
//Translation : "Choose a number to find its factorial" 🥖
scanf("%d", &num);
printf("factoriel de %d : %lu\n", num, factorial(num));
}
It is a very basic code to return factorial value but I'm just a beginner.

The factorial function grows very fast. Just about no matter what type you use for your computations, it's going to overflow pretty soon.
On a machine where type unsigned long has 32 bits (which is all that's guaranteed), your program can correctly compute 12! = 479001600 (but nothing larger). I suspect that's what you're seeing.
On a machine where type unsigned long has 64 bits, your program can correctly compute 20! = 2432902008176640000. (My machine has 64-bit longs, and I used your program to compute this result, and it worked fine.)
So your program is actually fine; I can't see anything wrong with it. (Well, there's an unused variable liste, and a stray loaf of bread in a comment. :-) )
If your compiler and C library both support type long long, you can try this to increase the range on your machine:
#include <stdio.h>
unsigned long long factorial(int num) {
if (num < 0) {
return 0;
} else if (num <= 1 ) {
return num;
} else {
return num * factorial(num - 1);
}
}
int main(void) {
int num;
printf("Choisir un nombre pour trouver son factoriel : ");
scanf("%d", &num);
printf("factoriel de %d : %llu\n", num, factorial(num));
}
But, again, this'll only get you up to 20!. (In this version I have also cleaned up the logic of your factorial function slightly.)
If %llu doesn't work, you can try %Lu.
Some compilers support a 128-bit type (I think gcc calls it _uint128_t or something like that), and this could theoretically get you up to 34! = 295232799039604140847618609643520000000.
But beyond that you'd have to use a "multiple precision" or "arbitrary precision" library such as GMP. For example, 100! has 525 bits, and 1000! has 8530 bits.

Related

Why does C outputs gibberish results when operation on an integer greater than 10 digits?

The code given below works fine up-to 10 digits with (int data-type) , but for numbers exceeding 10 digits it failed , so i tried unsigned long long int. But now my output is fixed to 15 , idk why? Consider me very new to C , i have mediocre python background though!
I am using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609
#include <stdio.h> //Get number of digits in a int
unsigned long long int get_len();
void main() {
unsigned long long int num;
printf("Enter the number:");
scanf("%d",&num);
printf("\nThe length of number is is: %d \n",get_len(num));
}
unsigned long long int get_len(unsigned long long int z) {
unsigned long long int i = 1;
while (1) {
if ((z/10) > 1) {
//printf("Still greater than 1");
i++;
z = z/10;
continue;}
else {
return(i+1);
break;}}}
You have used wrong format specifier. it would be scanf("%llu",&num);
Using the wrong format specifer in scanf is undefined behavior.
Apart from what is being mentioned, your length finding logic is wrong in that it will fail for single digit numbers and also for multidigit one.
For 1 it will return number of digits 2 and similarly for other numbers. (like for 12 it will return 3).
For larger numbers you will have options of opting an library (big number processing) or write one of as you need.
I would scan the numbers like this
if( scanf("%llu",&num) != 1) { /* error */}. More clearly check the return value of scanf.
Here's another implementation. This fixes a few issues:
Main return type must be int.
unsigned int is more than sufficient as get_len() return type.
unsigned int and unsigned are the same. Also unsigned long long int can be stripped of int.
#include <stdio.h>
unsigned get_len();
int main()
{
unsigned long long num;
printf("Enter the number: ");
scanf("%llu", &num);
printf("\nThe length of number is: %u\n", get_len(num));
}
unsigned get_len(unsigned long long z)
{
return (z / 10 > 0) ? get_len(z / 10) + 1 : 1;
}

How to convert decimal to binary in 64 bits?

so I have this code
int main()
{
int n, c, k;
printf("Enter an integer\n");
scanf("%d", &n);
printf("%d in binary is:\n", n);
for (c = 31; c >= 0; c--)
{
k = n >> c;
if (k & 1)
printf("1");
else
printf("0");
}
printf("\n");
return 0;
}
It converts decimal into binary but only in 32 bits. When I change it into 64 bits it doesn't work (it seems like it just doubles the result from 32 bits). At the same time it works fine with 8 or 4 bits etc.
What am I doing wrong?
It converts decimal into binary but only in 32 bits. When I change it into 64 bits it doesn't work (it seems like it just doubles the result from 32 bits).
The problem is here.
int n, c, k;
printf("Enter an integer\n");
scanf("%d", &n);
n is an int which can be as small as 16 bits. It could be 64 bits, but it's probably 32 bits. When you try to enter a 64 bit number you'll get garbage.
#include <stdio.h>
int main() {
int n;
printf("sizeof(int) == %zu\n", sizeof(int));
printf("Enter an integer\n");
scanf("%d", &n);
printf("n = %d\n", n);
}
$ ./test
sizeof(int) == 4
Enter an integer
12345678901
n = -539222987
Instead, you can use a long long int which has a minimum size of 64 bits or int64_t from stdint.h which is exactly 64 bits. I have a preference for using the explicit width types in code that requires a specific width to make it more obvious to the reader.
long long int uses %lld for scanf and printf while int64_t uses macros from inttypes.h. The code below takes advantage of C automatically concatenating constant strings; "foo" "bar" and "foobar" are equivalent.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main() {
int64_t n;
printf("Enter an integer\n");
scanf("%"SCNd64, &n);
printf("n = %"PRId64"\n", n);
}
$ ./test
Enter an integer
12345678901
n = 12345678901
The problem is your n & k variables' data type. They are integer. Check your platform's data type size using sizeof(int).
When you change to 64-bits, these variables can't hold 64-bit values.
HTH!
the following code is one way to handle the problem:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
long long unsigned int n;
long long int c;
long long unsigned int k;
printf("Enter an integer\n");
if( 1 != scanf("%llu", &n) )
{
perror( "scanf for 64 bit number failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("%llu in binary is:\n", n);
for (c = 63; c >= 0; c--)
{
k = n >> c;
if (k & 1)
putc('1', stdout);
else
putc('0', stdout);
}
printf("\n");
return 0;
} // end function: main
and here is the output from a typical run of the program:
Enter an integer
6789097860397846
6789097860397846 in binary is:
0000000000011000000111101010011000000110010100000111101100010110

Is there really no way to print a signed number without a sign in C?

I tried converting it to unsigned and declaring it as unsigned. It didn't work.
#include <stdio.h>
int main(void)
{
int number, modulo;
int result = 0;
printf("Please provide an integer: ");
scanf("%i", &number);
while (number != 0) {
modulo = number % 10;
result += modulo;
number = number / 10;
}
printf("%i", result);
printf("The sum of the digits of provided number is %i\n", result);
return 0;
}
Assuming that x is an int variable, printf("%d", x<0 ? -x : x) prints x without a sign for all values except INT_MIN on a 2's complement platform.
R.. below has suggested:
printf("%u", (unsigned) (x<0 ? (-1 - x) + 1 : x);
… because that handles INT_MIN too for any reasonable platform.
#define ABS(x) (((x)<0)?(-(x)):(x))
(Or as correctly pointed out, there's the built-in abs() in stdlib).

What is the largest prime factor of the number 600851475143?

I want to know that what is the error in my code.
int main () {
long long int number, large_factor=0, i=2;
printf ("Enter a number : ");
scanf ("%ld", &number);
while (number!=1) {
if (number%i==0) {
while (number%i==0) {
printf ("%ld\t", i);
number/=i;
}
large_factor=i;
}
i++;
}
printf ("\n\nThe largest prime factor is : %ld\n\n", large_factor);
return 0;
}
This code is running fine for smaller numbers but why it is failing for the large numbers?
Your format specifier everywhere is for long int you should use "%lld".
When I fix the format specifiers it runs fine for 600851475143 giving the largest prime factor 6857.
There must be something else going on. Assuming your compiler is compliant long long int should (at minimum) be a 64-bit integer and easily large enough to accommodate that value.
Try
printf("long long int max : %lld\n",LLONG_MAX);
Having added #include <limits.h> at the top.
It should produce a value no less than 9223372036854775807 and probably that exact number.
Here:
#include <limits.h>
#include <stdio.h>
int main () {
printf("long long int max : %lld\n",LLONG_MAX);
long long int large_factor=0, i=2;
long long int number=600851475143;
while (number!=1) {
if (number%i==0) {
while (number%i==0) {
printf ("%lld\t", i);
number/=i;
}
large_factor=i;
}
i++;
}
printf ("\n\nThe largest prime factor is : %lld\n\n", large_factor);
return 0;
}

Decimal To Binary conversion using Array and Stack

This is the C Program I have written to convert a Decimal number to it's equivalent Binary number. I have used Stack (implemented using array) and the following algorithm:
Number is divided and remainders are pushed in stack.
Remainders are popped one at a time and converted into Binary
The Problem is that the program works fine for numbers up to 3, after that from 4 on wards, each Binary Number comes one less than the actual number.
// Decimal to Binary conversion using Stack
#include<stdio.h>
#include<math.h>
#define max 20
int top=-1, stk[max];
void push(int);
int pop(void);
int main()
{
int i,num,x,flag=0,s, bin=0, factor;
printf("Enter any decimal number: ");
scanf("%d",&num);
while(num>0)
{
if(num==1)
push(num);
else
{
x = num%2;
push(x);
}
num/=2;
flag++;
}
for(i=0;i<flag;i++)
{
s = pop();
bin = bin + s*pow(10,(flag-1-i));
}
printf("\nEquivalent Binary number is --> %d",bin);
return 0;
}
void push(int n)
{
if(top == max-1)
{
printf("Error! Overflow");
return;
}
stk[++top] = n;
}
int pop(void)
{
int y;
if(top == -1)
{
printf("Error! Underflow");
return;
}
y = stk[top];
top = top-1;
return y;
}
Will anybody help me by finding the logical flaw?
Thank You
My answer is your program is unnecessarily complicated.
#include<stdio.h>
int main()
{
unsigned num, i, zeros = 0;
printf("Enter a decimal number: ");
scanf("%u", &num);
printf ("Decimal %u in binary is ", num);
for (i=sizeof(unsigned)*8; i>0; i--)
{
if ((int)num < 0) // get MSB
zeros = printf ("1"); // cancel 0-suppresion
else if (zeros)
printf ("0");
num <<= 1;
}
printf ("\n");
return 0;
}
The function pow return a double that can have a 9999999... after the decimal point, which is rounded to the floor when it is casted to int, you can fix your problem using ceil() function, that returns the smallest integer value greater than or equal the argument, like this.
bin = bin + ceil(s*pow(10,(flag-1-i)));
//C Program to convert Decimal to binary using Stack
#include<stdio.h>
#define max 100
int stack[max],top=-1,i,x;
/*------ Function Prototype------------*/
void push (int x)
{
++top;
stack [top] = x;
}
int pop ()
{
return stack[top];
}
/*-------------------------------------*/
void main()
{
int num, total = 0,item;
printf( "Please enter a decimal: ");
scanf("%d",&num);
while(num > 0)
{
total = num % 2;
push(total);
num /= 2;
}
for(i=top;top>-1;top--)
{
item = pop ();
printf("%d",item);
}
}
Here is a simpler version of your above program
int main(){
int n,remainder;
printf("Enter a decimal number:");
scanf("%d",&n);
while(n!=0){
remainder = n%2;
n = n/2;
push(remainder); // inserting in stack
}
display(); // displaying the stack elements
}
reference of above code
C program to Convert Decimal number into Binary using Stack
So I've done the math on several numbers, and this appears to be correct. I would agree with others that this is needlessly complicated, but that is not causing your issues on it's own, it's just making them harder to find.
So the output of this program appears correct, from a logical standpoint. Lets look into other potential issues:
You're indexing an array with an int that you initialize to -1
This is bad practice, and unnecessary. Array indexes in C can never be negative, so the compiler will assume this is an unsigned number, so if you have a 32 bit processor, it will assume you're trying to get array[2^32 - 1], which is not what you want. Always use a unsigned value for array indexes
What MIGHT be happening, and I'm not certain, is that your compiler is doing something with this behind the scenes which is screwing up your program, it's really hard to say. But it's probably attempting to convert your negative number into an unsigned int before you do your addition. Fix this by changing your declaration of top to:
unsigned int top = 0;
and changing where you access top from:
stk[++top] = n;
to
stk[top++] = n;
You will also have to change
y = stk[top];
top = top-1;
to
top = top-1;
y = stk[top];
I'd say start there. I'd also suggest removing the pow line, and just individually printing each piece of the array, because it will output in the same way, and you already have all the info there ie.
PRINTF("%d%d%d",stk[2],stk[1],stk[0]);

Resources