What is the limit to output numbers in C? - c

I was practicing programming in C, and when I ran this code, it came to a point where the outputting numbers just gave up lol, it was around the 30th number of the sequence.
What is the limit to output numbers in C?
(I was trying the Fibonacci sequence)
int main() {
int fibo, i, n, a, aux;
printf("Enter a number: ");
scanf("%d", &fibo);
n = 1; a = 1;
printf("1 1 ");
for(i = 3; i <= fibo; i++){
/* aux = n;
n = n + a;
a = aux;*/
n += a;
a = n - a;
printf("%d ", n);
}
}

What is the limit to output numbers in C?
There is no such limit. You can create a library to do arithmetic operations on arbitrary large numbers - and output them.
The question should probably be "what ranges can the fundamental types in C represent?" - and there are different limits for the different fundamental types.
Here's an incomplete list of some types taken from limits.h:
INT_MIN - minimum value of int
INT_MAX - maximum value of int
LLONG_MIN - minimum value of long long int
LLONG_MAX - maximum value of long long int
And from float.h:
DBL_MIN - minimum, normalized, positive value of double (typically 0.)
-DBL_MAX - lowest finite value representable by double
DBL_MAX - maximum finite value of duuble
Note that
an int is required to be at least 16 bit wide, but is often 32.
a long int is required to be at least 32 bit wide and often is.
a long long int is required to be at least 64 bites wide.
Depending on the type's bit width and how the implementation make use of these bits (two's complement, ones' complement, sign–magnitude and for floating points, if they use IEEE 754 or something else) affects the ranges they can represent.

Fibonacci numbers get very large very quickly, and will exceed the range of native integer types for relatively small n. On my system, the largest Fibonacci number I can compute with the following code using a regular signed int is F(44):
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main( int argc, char **argv )
{
if ( argc < 2 )
{
fprintf( stderr, "USAGE: %s n\n", argv[0] );
exit( 0 );
}
int n = strtol( argv[1], NULL, 10 );
int f[3] = { 0, 1, 0 };
printf( "INT_MAX = %d\n", INT_MAX );
for ( int i = 1; i <= n && INT_MAX - f[2] > f[1] + f[0]; i++ )
{
f[2] = f[1] + f[0];
f[0] = f[1];
f[1] = f[2];
printf( "fib %3d = %10d\n", i, f[2] );
}
return 0;
}
Output:
$ ./fib 50
INT_MAX = 2147483647
fib 1 = 1
fib 2 = 2
fib 3 = 3
fib 4 = 5
fib 5 = 8
fib 6 = 13
fib 7 = 21
fib 8 = 34
fib 9 = 55
fib 10 = 89
fib 11 = 144
fib 12 = 233
fib 13 = 377
fib 14 = 610
fib 15 = 987
fib 16 = 1597
fib 17 = 2584
fib 18 = 4181
fib 19 = 6765
fib 20 = 10946
fib 21 = 17711
fib 22 = 28657
fib 23 = 46368
fib 24 = 75025
fib 25 = 121393
fib 26 = 196418
fib 27 = 317811
fib 28 = 514229
fib 29 = 832040
fib 30 = 1346269
fib 31 = 2178309
fib 32 = 3524578
fib 33 = 5702887
fib 34 = 9227465
fib 35 = 14930352
fib 36 = 24157817
fib 37 = 39088169
fib 38 = 63245986
fib 39 = 102334155
fib 40 = 165580141
fib 41 = 267914296
fib 42 = 433494437
fib 43 = 701408733
fib 44 = 1134903170
If I switch to unsigned int, I can compute up to F(45). If I use long, I can get up to F(90). But even if I use unsigned long long, I'll still exceed its range with relatively small n.
To compute Fibonacci sequences for arbitrarily large n, you'll need a third-party bignum library like GMP:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <gmp.h>
int main( int argc, char **argv )
{
if ( argc < 2 )
{
fprintf( stderr, "USAGE: %s n\n", argv[0] );
exit( 0 );
}
int n = strtol( argv[1], NULL, 10 );
mpz_t f[3];
mpz_init_set_str( f[0], "1", 10 );
mpz_init_set_str( f[1], "1", 10 );
for ( int i = 1; i <= n; i++ )
{
mpz_add( f[2], f[1], f[0] );
mpz_set( f[0], f[1] );
mpz_set( f[1], f[2] );
gmp_printf( "fib %d = %Zd\n", i, f[2] );
}
return 0;
}
For n == 1000, I get
fib 1000 = 113796925398360272257523782552224175572745930353730513145086634176691092536145985470146129334641866902783673042322088625863396052888690096969577173696370562180400527049497109023054114771394568040040412172632376
Edit
Gah, the sequence starts off wrong - it should be 1, 1, 2, .... But my main point remains.

Related

What's the Big O time complexity of this code?

#include <stdio.h>
int F(int L[], int p, int q) {
if (p < q) {
int r, f1, f2;
r = (p + q) / 2;
f1 = 2 * F(L, p, r);
f2 = 2 * F(L, r + 1, q);
return f1 + f2;
} else if (p == q) {
return L[p] * L[p];
}else{
return 0;
}
}
int main(void) {
int arr[8] = {1,2,3,4,5,6,7};
printf("%d", F(arr, 0, 7));
}
Someone said the time complexity of this code is O(n).
I don't understand it at all...
Isn't it O(logN) ???
Answer: The Big-O complexity is O(N)
Explanation:
The program takes a range of some size (i.e. q - p + 1) and cut that range into 2 half. Then it calls the function recursively on these two half ranges.
That process continues until the range has size 1 (i.e. p == q). Then there is no more recursion.
Example: Consider a start range with size 8 (e.g. p=0, q=7) then you will get
1 call with range size 8
2 calls with range size 4
4 calls with range size 2
8 calls with range size 1
So 7 calls (i.e. 1+2+4) with range size greater than 1 and 8 calls with range size equal to 1. A total of 15 calls which is nearly 2 times the starting range size.
So for a range size being a power of 2, you can generalize to be
Number of calls with range size greater than 1:
1+2+4+8+16+...+ rangesize/2 = rangesize - 1
Number of calls with range size equal to 1:
rangesize
So there will be exactly 2 * rangesize - 1 function calls when range size is a power of 2.
That is Big-O complexity O(N).
Want to try it out?
#include <stdio.h>
unsigned total_calls = 0;
unsigned calls_with_range_size_greater_than_one = 0;
unsigned calls_with_range_size_equal_one = 0;
int F(int L[], int p, int q) {
++total_calls;
if (p < q) {
++calls_with_range_size_greater_than_one;
int r, f1, f2;
r = (p + q) / 2;
f1 = 2 * F(L, p, r);
f2 = 2 * F(L, r + 1, q);
return f1 + f2;
} else if (p == q) {
++calls_with_range_size_equal_one;
return L[p] * L[p];
}else{
return 0;
}
}
int arr[200] = {1,2,3,4,5,6,7};
int main(void) {
for (int i=3; i < 128; i = i + i + 1)
{
total_calls=0;
calls_with_range_size_greater_than_one=0;
calls_with_range_size_equal_one=0;
F(arr, 0, i);
printf("Start range size: %3d -> total_calls: %3u calls_with_range_size_greater_than_one: %3u calls_with_range_size_equal_one: %3u\n", i+1, total_calls, calls_with_range_size_greater_than_one, calls_with_range_size_equal_one);
}
return 0;
}
Output:
Start range size: 4 -> total_calls: 7 calls_with_range_size_greater_than_one: 3 calls_with_range_size_equal_one: 4
Start range size: 8 -> total_calls: 15 calls_with_range_size_greater_than_one: 7 calls_with_range_size_equal_one: 8
Start range size: 16 -> total_calls: 31 calls_with_range_size_greater_than_one: 15 calls_with_range_size_equal_one: 16
Start range size: 32 -> total_calls: 63 calls_with_range_size_greater_than_one: 31 calls_with_range_size_equal_one: 32
Start range size: 64 -> total_calls: 127 calls_with_range_size_greater_than_one: 63 calls_with_range_size_equal_one: 64
Start range size: 128 -> total_calls: 255 calls_with_range_size_greater_than_one: 127 calls_with_range_size_equal_one: 128

Unsigned long long outputs 0

I have this issue where I need to square line in Pascal's triangle and when it comes to big numbers it only outputs 0
unsigned long sum_squared(const int line){
unsigned long long n = 2*line;
unsigned long long x1 = factorial(line);
unsigned long long k = x1*x1;
unsigned long long x = factorial(n)/(k);
return x;
}
unsigned long long factorial(unsigned long long n) {
if (n == 0){
return 1;
}
return n * factorial(n - 1);
}
I test it with:
printf("%lu\n", sum_squared(14));
The key word here is "outputs". You need the correct format specifier to output unsigned long long: %llu.
The maximum number should be 7219428434016265740 and it equals sum_squared(33)
The code tries to evaluate the sum using (directly) the formula
⎛ 2n ⎞ (2n)!
⎜ ⎟ = ―――――
⎝ n ⎠ n!·n!
As noted in the other answers and comments, this leads to overflow of the intermediate results.
Luckily, this expression can be simplified and evaluated safely (without overflowing 64-bit wide unsigned integers) up to the required value.
We can start dividing both the numerator and the denominator by n!
(2n)! (n+1)·(n+2)· ... ·(n+n) (n+1)·(n+2)· ... ·(2n-2)·(2n-1)·(2n)
――――― = ――――――――――――――――――――――― = ――――――――――――――――――――――――――――――――――――
n!·n! n! 1·2· ... ·(n-1)·n
Also note that the higher half terms in the denominator have the corresponding doubles in the numerator. Let's see a couple of examples
⎛ 8 ⎞ 8! 5·6·7·8 5·2·7·2
⎜ ⎟ = ――――― = ――――――― = ――――――― = 70
⎝ 4 ⎠ 4!·4! 1·2·3·4 1·2
⎛ 10 ⎞ 10! 6·7·8·9·10 2·7·2·9·2 70
⎜ ⎟ = ――――― = ―――――――――― = ――――――――― = 252 = ―― · 9 · 2
⎝ 5 ⎠ 5!·5! 1·2·3·4·5 1·2 5
⎛ 12 ⎞ 12! 7·8·9·10·11·12 7·2·9·2·11·2 252
⎜ ⎟ = ――――― = ―――――――――――――― = ―――――――――――― = 924 = ――― · 11
⎝ 6 ⎠ 6!·6! 1·2·3·4·5·6 1·2·3 3
Now we can derive a couple of recurrence relations that let us evaluate the sum at a given n from the sum at n - 1
sum(1) = 2
sum(n-1)
sum(n) = ―――――――― · (2·n - 1) when n is even
n/2
sum(n-1)
sum(n) = ―――――――― · (2·n - 1) · 2 when n is odd
n
Note that the divisions (which are always exact, but I won't demonstrate that) are performed before the multiplications, avoiding unnecessary overflows.
Those formulas produce the following sequence
1 2
2 6
3 20
4 70
5 252
6 924
7 3432
8 12870
9 48620
10 184756
11 705432
12 2704156
13 10400600
14 40116600
15 155117520
16 601080390
17 2333606220
18 9075135300
19 35345263800
20 137846528820
21 538257874440
22 2104098963720
23 8233430727600
24 32247603683100
25 126410606437752
26 495918532948104
27 1946939425648112
28 7648690600760440
29 30067266499541040
30 118264581564861424
31 465428353255261088
32 1832624140942590534
33 7219428434016265740
The next value, 34, can't be calculated this way (using a 64-bit type).
28! = 304888344611713860501504000000 which is larger than maximum unsigned long long 18446744073709551615. It wraps over (modulo ULLONG_MAX)and the result is smaller than k. The division will be 0
You use the wrong printf format.
unsigned long long factorial(unsigned long long n)
{
if (n == 0) return 1;
return n * factorial(n - 1);
}
unsigned long sum_squared(const int line)
{
unsigned long long n = 2*line;
unsigned long long x1 = factorial(line);
unsigned long long k = x1*x1;
unsigned long long x = factorial(n)/(k);
printf("%llu %llu %llu %llu %llu\n", n, x1, k, x , factorial(n));
return x;
}
int main(void)
{
printf("%llu\n", sum_squared(14));
}
output:
28 87178291200 18442642257371725824 0 12478583540742619136
18417982275456073728

recursive function in c for the furmula: a(n)=a(n-1)+a(n-2)

I am trying to write a recursive function for the formula:
a(n)=a(n-1)+a(n-2)
I've tried to simply write it out:
unsigned int ladder(unsigned int n)
{
unsigned int ret=0;
if (n < 1)
return ret;
ret = ladder(n - 1) + ladder(n - 2);
}
but it goes into stack overflow when calling for ladder(n-2)
(for some reason it sets n as a very large integer)
I feel like I'm missing something very basic but can't figure out what.
The function returns nothing in case when n is not less than 1.
Also when n is equal to 1 then the expression n - 2 yields the maximum value that can be stored in object of the type unsigned int.
The function can be declared and defined the following way
unsigned long long int ladder( unsigned int n )
{
return n < 2 ? n : ladder( n - 1 ) + ladder( n - 2 );
}
Here is a demonstration program.
#include <stdio.h>
unsigned long long int ladder( unsigned int n )
{
return n < 2 ? n : ladder( n - 1 ) + ladder( n - 2 );
}
int main( void )
{
for ( unsigned int i = 0; i < 25; i++ )
{
printf( "%llu ", ladder( i ) );
}
putchar( '\n' );
}
The program output is
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368

Binary to decimal algorithm in c giving strange results

Hi i'm fairly new to c but for a program I'm writing I need to convert binary strings to decimal numbers. here is my current code:
int BinaryToInt(char *binaryString)
{
int decimal = 0;
int len = strlen(binaryString);
for(int i = 0; i < len; i++)
{
if(binaryString[i] == '1')
decimal += 2^((len - 1) - i);
printf("i is %i and dec is %i and the char is %c but the length is %i\n", i, decimal, binaryString[i], len);
}
return decimal;
}
int main(int argc, char **argv)
{
printf("%i", BinaryToInt("10000000"));
}
and here is the output:
i is 0 and dec is 5 and the char is 1 but the length is 8
i is 1 and dec is 5 and the char is 0 but the length is 8
i is 2 and dec is 5 and the char is 0 but the length is 8
i is 3 and dec is 5 and the char is 0 but the length is 8
i is 4 and dec is 5 and the char is 0 but the length is 8
i is 5 and dec is 5 and the char is 0 but the length is 8
i is 6 and dec is 5 and the char is 0 but the length is 8
i is 7 and dec is 5 and the char is 0 but the length is 8
5
I'm confused as to why this doesn't work, all help is greatly appreciated. Thanks in advance!
Ps: I'm used to java so at the moment C just makes me cry
The ^ operator is not for exponentiation, but is instead the bitwise XOR operator.
If you want to raise a number to a power of 2, use the left shift operator << to shift the value 1 by the exponent in question.
decimal += 1 << ((len - 1) - i);
The trick is the same as with any number base: for each incoming digit, multiply the accumulator by the number base and add the digit.
#include <stdio.h>
#include <string.h>
int BinaryToInt(char *binaryString)
{
int decimal = 0;
int len = strlen(binaryString);
for(int i = 0; i < len; i++) {
decimal = decimal * 2 + binaryString[i] - '0';
}
return decimal;
}
int main(void)
{
printf("%d", BinaryToInt("10000000"));
return 0;
}
Program output:
128

Binary division in C

#include "stdio.h"
int bdiv( int dividend , int divisor )
{
int remainder = dividend ;
int quotient = 0 ;
int i ;
for( i = 0 ; i < 17 ; i++ )
{
remainder = remainder - divisor ;
if( (remainder & 0x8000) )
{
remainder = remainder + divisor ;
quotient = quotient << 1 ;
}
else
quotient = ( quotient << 1 ) | 0x1 ;
divisor = divisor >> 1 ;
}
return quotient ;
}
int main()
{
int a = 7 ;
int b = 2 ;
printf( "%d\n" , bdiv(a,b) ) ;
}
Pseudo-Code of the algorithm I tried to implement :
START
Remainder = Dividend ;
Quotient = 0 ;
1.Subtract Divisor register from remainder and place result in remainder .
2. Test Remainder
2a . If remainder >= 0 shift quotient to right setting rightmost bit to 1
2b. If remainder < 0 , restore the original value of the remainder register . Also shift the quotient register to the left setting the new least significant bit to 0 .
3. Shift the divisor right 1 bit .
4. is it the 33rd repetition ( for 32 bit division ) ? No : GOTO 1
Yes : STOP
I wrote this program for binary division in C for 16 bit division and it's not working . Can anyone suggest me what's not working ?
It is giving output as 131071 for a division of 7 by 2 .
The second shift needs to be:
quotient = (( quotient >> 1 ) | 0x1) ;
Also, why not:
if (remainder < 0 )
???
#include "stdio.h"
int bdiv( int dividend , unsigned divisor )
{
divisor<<=16;
int i = 17 ;
do {
dividend -= divisor ;
if (dividend < 0) dividend += divisor ;
else dividend++;
i--;
if (i) dividend<<=1;
// printf( "%d, %d\n" , dividend, divisor ) ;
} while (i);
return dividend ;
}
int main()
{
int a []= {631, 76, 760, 7600, 76000, 450333, 450333, 450333, 450333};
int b []= {7, 75, 750, 7500, 75000, 77, 777, 7777, 77777} ;
union doubleint {
struct {
short int quotient;
short unsigned remainder;
}part;
int value;
} c;
for (unsigned char i = 0; i < 9; i++){
c.value = bdiv(a [i],b [i]);
printf( "%d / %d = %d + %d / %d\n" , a[i], b[i], c.part.quotient, c.part.remainder, b[i] ) ;
}
/*
unsigned c = bdiv (a,b);
printf ("%d, %d\n", c&0xffff, (c>>16)&0xffff);
*/
}
/*
631 / 7 = 90 + 1 / 7 Correct
76 / 75 = 1 + 1 / 75 Correct
760 / 750 = 1 + 10 / 750 Correct
7600 / 7500 = 1 + 100 / 7500 Correct
76000 / 75000 = 8 + 288 / 75000 WRONG: 75000 doesn't fit in 2 bytes
450333 / 77 = 5848 + 37 / 77 Correct: dividend does not have to fit in 2 bytes
450333 / 777 = 579 + 450 / 777 Correct
450333 / 7777 = 57 + 7044 / 7777 Correct
450333 / 77777 = 36 + 9657 / 77777 WRONG: 77777 does not fit in 2 bytes
*/

Resources