I want to obtain the binary logarithms of the numbers 1 to 2048, but I don´t know why it doesn´t work, it doesn´t obtain the right numbers.
If I use floats, it works, but it used to work with integers, i have already done a program with this method and now it doesn´t work because of that. Changing the unsigned int to int doesn´t work. Someone knows why?
for(unsigned int numero=1;numero<=2048;numero*=2)
{
int x=log10(numero)/log10(2);
printf("%d\n",x);
}
return 0;
It prints:
0 1 2 2 4 5 5 6 8 9 10 11
It should be:
0 1 2 3 4 5 6 7 8 9 10 11
Looks like it works for some numbers, but i don´t understand why it doesn´t work for all numbers.
log10 returns a floating point number (double). The value of log10 is not exactly representible in floating point for most numbers you pass, therefore you might get something like log10(8)/log10(2) == 2.9999999 instead of an exact 3. The conversion to int truncates it down to 2. To fix that you should round properly:
int x = lrint(log10(numero)/log10(2));
Or in case your compiler doesn't have the lrint function you can use:
int x = log10(numero)/log10(2) + 0.5;
which would work for this case.
Notice that there are alternative ways to calculate the desired result. Since floating-point numbers already store the exponent in base 2, you can retrieve it with a call to frexp:
int x;
frexp(numero, &x);
Another way would be to avoid floating point math altogether and use an intrinsic to get the index of the last bit set in numero. Unfortunately there's no cross-platform way to do that.
Related
#include <stdio.h>
#include <stdlib.h>
int factorial(int i) {
if(i == 1) {
return 1;
}
else {
return i*factorial(i - 1);
}
}
int combination(int l, int m) {
return factorial(l)/(factorial(l-m)*factorial(m));
}
int main() {
int n,r;
printf("Input taken in form of nCr\n");
printf("Enter n: ");
scanf("%d", &n);
printf("Enter r: ");
scanf("%d", &r);
int y = combination(n, r);
printf("Result: %d", y);
return 0;
}
Tried to make a simple code for calculating the combination function in maths. It worked for small values and basically works till n = 12, and gives wrong values from n = 13 and onwards.
Also for n = 15 and r = 2, it returns the result -4.
And it gives the error
segmentation fault (core dumped)
for n = 40 and r = 20.
I would like to know how to solve this problem and why exactly is this happening.
The value of 13! is 6227020800 which is too large to fit into an 32 bit integer. By attempting to calculate this factorial or larger results in overflowing a 32 bit int. Signed integer overflow invokes undefined behavior.
In some cases, this undefined behavior manifests as outputting the wrong value, while in others it manifests as a crash. The cases where it crashes the factorial function is most likely passed a value less than 1, meaning that the recursive calls will attempt to go all the way down to INT_MIN but fills up the stack before that can happen.
Even changing to long long isn't enough to fix this, as the intermediate results will overflow that. So how do you fix this? If you were calculating these values by hand you wouldn't multiply out all of the numbers together then divide two huge numbers. You'd write out the factors and cancel out terms from the top and bottom of the equation. For example, suppose you wanted to calculate 12C7. You would write it out like this:
12 * 11 * 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
------------------------------------------------
( 5 * 4 * 3 * 2 * 1 ) * (7 * 6 * 5 * 4 * 3 * 2 * 1)
Then cancel out 7! from the top and bottom:
12 * 11 * 10 * 9 * 8
---------------------
5 * 4 * 3 * 2
Then cancel out other terms:
12 * 11 * 10 * 9 * 8 12 * 11 * 2 * 9 * 8 12 * 11 * 2 * 9
--------------------- = -------------------- = --------------- = 4 * 11 * 2 * 9
5 * 4 * 3 * 2 4 * 3 * 2 3
Then multiply what's left:
4 * 11 * 2 * 9 = 792
Now do this in code. :) Be sure to change all of your datatypes to long long, as the result of 40C20 is still a bit larger than what a 32-bit int can hold. This type is guaranteed to be at least 64 bits.
This is an overflow problem here. You result is above the max int value.
13! = 6227020800
Wich is more than INT_MAX (2147483647). If you want to handle larger numbers you should either use other variables types (for example unsigned long long), or handle the overflow in your function to avoid memory crashes.
Here is a topic that could be interesting about overflow checking in c here.
Also for n = 15 and r = 2, it returns the result -4
When a variable overflowed, it can underflow and
overflow in cycle. This is why you are getting negative values. I'm not sure but I think this is related. If somebody can validate this it would be great.
I guess there are 2 effects interacting:
Your integers overflow, that is the value of factorial(i) will become negative for sufficiently big i leading to
Your recursion (having factorial call itself) consumes all your stack space.
Try to change the condition in factorial from if(i == 1):
int factorial(int i) {
if(1 == i) {
return 1;
} else if(1 > i) {
return -1;
}
return i * factorial(i - 1);
}
This should have you get rid of the SEGFAULT.
For the integer overflow, the only possible solution would be to not rely on C integer arithmethic but using some bignum library (or write the code on your own).
Some explanation for what is probably going on:
As #WhozCraig pointed out, integers can only keep a range of numbers up to INT_MAX. However, factorial(i) just explodes even for relatively small numbers.
C however does not capture this exception and your integers will silently overflow to negative numbers.
This means at some point you start feeding factorial with negative numbers.
However, for each function call, some data has to be pushed onto the stack (usually the return address and local variables, possibly including the function arguments).
This memory will be released only after the function returns.
This means, if you call factorial(40), if everything works integer wise, you will eat up 40 times the amount of memory for 1 call to factorial.
Since your factorial does not handle negative numbers correctly, it will end up calling itself endlessly, overflowing from time to time, until the condition i == 1 at some point is randomly hit.
Ostensibly in most cases, this does not happen before your stack is exhausted.
When I run your program in a debugger with n = 40 and r = 20 on a 32-bit binary compiled with Microsoft Visual Studio, then I don't get a segmentation fault, but I get a division by zero error in the following line:
return factorial(l)/(factorial(l-m)*factorial(m));
factorial(l-m) and factorial(m) both evaluate to factorial(20), which is 2,192,834,560.
Assuming that sizeof(int) == 4 (32-bit), this number cannot be represented by a signed int. Therefore, the int overflows, which, according to the official C standard, causes undefined behavior.
However, even if the behavior is undefined, I can reasonably speculate that the following happens:
Due to the overflow, the number 2,192,834,560 will become -2,102,132,736. This is because the second number corresponds to the first number in Two's complement binary representation.
Since this number is multiplied with itself in your code (assuming n = 40 and r = 20), then the result of the multiplication will be 4,418,962,039,762,845,696. This number certainly does not fit into a signed int, so that an overflow occurs again.
The hexadecimal representation of this number is 0x3D534E9000000000.
Since this large number does not fit into a 32-bit integer, all the excess bits are stripped off, which is equivalent to subjecting the result to modulo UINT_MAX + 1 (4,294,967,296). The result of this modulo operation is 0.
Therefore, the expression
factorial(l-m)*factorial(m)
evaluates to 0.
This means that the line
return factorial(l)/(factorial(l-m)*factorial(m));
will cause a division by zero exception.
One way of solving the problem of handling large numbers is to use floating point numbers instead of integers. These can handle very large numbers without overflowing, but you may lose precision. If you use double instead of float, you will not so easily lose precision and, even if you do, the precision loss will be smaller.
I came across this program to convert decimals numbers into their binary equivalent in C. I do not understand how the printf statement works in this program.
int main()
{
int N;
scanf("%d", &N); // Enter decimal equivalent here
for( int j = floor(log2(N)); j >= 0; j-- ){
printf("%d", (N >> j) & 1);
}
}
Let's take an example to get through this problem. Suppose you enter N=65. Its binary representation is - 1000001. When your given code goes through it, j will start at floor(log2(65)), which is 6. So, the given loop will run 7 times, which means 7 numbers will be printed out (which fits the fact that 65's binary representation has 7 digits).
Inside the loop - The number is shifted by j bits each time to the right. When 1000001 is shifted to the right by 6 bits, it becomes 0000001. If shifted by 5, it is 0000010, and so on. It goes down to a shift by 0 bits which is the original number. When each of these shifted numbers are &ed with 1, only the least significant bit (the right most bit) remains. And this digit can either be a 0 or a 1.
If you would have noticed each right shift divides the number by 2. So when 1000001 is shifted by 1 to make 0100000, it is the binary representation of 32, which indeed is 65/2 in C. After all, this is the way someone manually calculates the binary representation of a number. Each division by 2 gives you a digit (starting from the end) of the representation, and that digit is either a 0 or a 1. The & helps in getting the 0 or 1.
In the end, 65 becomes 1000001.
What it is doing is:
Finding the largest number j such that 2^j <= N
Starting at the jth bit (counting from the right) and moving to the right ...
chopping off all of the bits to the right of the current chosen bit
chopping off all of the bits to the left of current chosen bit
printing the value of the single remaining bit
The code actually has undefined behavior because you did not include <stdio.h>, nor <math.h>. Without a proper declaration of floor() and log2(), the compiler infers the prototype from the calling context and gets int log2(int) and int floor(int), which is incompatible with the actual definition in the C library.
With the proper includes, log2(N) gives the logarithm of N in base 2. Its integral part is the power of 2 <= N, hence 1 less than the number of bits in N.
Note however that this method does not work for negative values of N and only works by coincidence for 0 as the conversion of NaN to int gives 0, hence a single binary digit.
I have searched many articles on google for following question but still not find any good answer.
From my first look ,I able to get that int x:3 here 3 is width if we assign x value greater than 3 some negative value get printed and if we assign value less than 3 ,the assigned value to x get printed correctly.
Can anyone explain how the output is coming of this code.
#include<stdio.h>
1 struct Point
2 {
3 int x:3, y:4;
4 };
5
6 int main()
7 {
8 struct Point p1 = {6,3};
9
10 printf ("x = %d, y = %d", p1.x, p1.y);
11
12 return 0;
13 }
The output comes as:
x = -2, y = 3
when i included stdio.h header file warning vanished but the output of x get chnaged first without header file the value of x is coming -4 now with stdio.h header file the value of x becomes -2.Why this is happening??
Thanks in advance!!
You are trying to store the value 6 into a signed integer of 3 bits, where there are 2 value bits and 1 bit reserved for the sign. Therefore the value 6, which cannot fit in the 2 value bits, is converted to a signed value in an implementation-defined manner. Apparently by using Two's complement.
"warning: overflow in implicit constant conversion" tells you just that. The compiler tries show constant 6 into the signed type bit field. I cannot fit - you get an overflow, and then there's an implicit type conversion to signed type.
I need to specify that I need two numbers be the same upon 3rd decimal place: 1.2345 and 1.2348 is correct. But 1.2345 and 1.2388 is not correct. And I need let user specify how many places should program check.
I was thinking about something like that:
do {
x = f(i++);// will count some number with i iterations
x_next = f(i++);// will count some number with i+1 iterations
} while (fabs(x - x_next) > accuracy);// there should be some difference, cause more iterations = accurate number, but different numbers = different iterations needed
But I don't know how should I convert number 3 to 0.001.
Can you suggest me something please?
Divide 1.0 by 10 3 times to get 0.001.
To convert 3 to .001 use the pow() function. .001 = pow(10, -3) (It returns base to the power of exponent, in this case 10^-3.) You would need to include the math.h library to use pow().
A word of caution. abs(x-y)<.001 does not guarantee that they agree on 3 decimal places. For example, 1.00000 and .99999 don't agree on any decimal places but abs(1.00000-.99999)=.00001 < .001.
If you need to check if two numbers are the same upon 3rd decimal place, you can simply multiply both values with 1000 and compare them as integers.
You get the picture, you have to mutiply with 10^decimal_place.
EDIT:
If rounding is required, then simply add 5/10^(decimal_place+1) before multiplying.
Well, there is two ways to approach this:
If you want to see if the difference of two numbers is less than 10 to the power of minus your number (in your example 0.001), you can use the solutions provided. However, it says 1.3458 is equal to 1.3462, which doesn't seems what you wanted.
You can convert the numbers to integers before. In your example (3 decimal places), you can multiply your number by 1000 (10 to the power of 3), and get it's integer part (with an (int) cast), as in:
int multiplier = pow(10,decimalPlaces);
int number1 = (int) numberOriginal1*multiplier;
int number2 = (int) numberOriginal2*multiplier;
if(number1 == number2)
printf("Success\n");
else printf("Fail\n");
Hope that helps.
If you just want to give it as an output simply use printf("%.3f",number)
or if you want to it other way, just go through this question,
Rounding Number to 2 Decimal Places in C
This question already has answers here:
Floating point inaccuracy examples
(7 answers)
C++ floating point precision [duplicate]
(5 answers)
Closed 8 years ago.
I found this code snippet on Page 174, A Book on C -Al Kelley, Ira Pohl .
int main()
{
int cnt=0; double sum=0.0,x;
for( x=0.0 ;x!= 9.9 ;x+=0.1)
{
sum=sum +x;
printf("cnt = %5d\n",cnt++);
}
return 0;
}
and it became a infinite loop as the book said it would. It didnt mention the precise reason except saying that it had to do with the accuracy of the machine.
I modified the code to check if
x=9.9
would ever become true, i.e. x was attaining 9.9 by adding the following lines
diff=x-9.9;
printf("cnt =10%d \a x =%10.10lf dif=%10.10lf \n",++cnt,x,diff);
and i got the following lines among the output
cnt =1098 x =9.7000000000 dif=-0.2000000000
cnt =1099 x =9.8000000000 dif=-0.1000000000
cnt =10100 x =9.9000000000 dif=-0.0000000000
cnt =10101 x =10.0000000000 dif=0.1000000000
cnt =10102 x =10.1000000000 dif=0.2000000000
if x is attaining the value 9.9 exactly , why is it still a infinite loop?
You are simply printing the number with too poor accuracy to notice that it isn't exact. Try something like this:
#include <stdio.h>
int main()
{
double d = 9.9;
if(d == 9.9)
{
printf("Equal!");
}
else
{
printf("Not equal! %.20f", d);
}
}
Output on my machine:
Not equal! 9.90000000000000035527
The book is likely trying to teach you to never use == or != operators to compare floating point variables. Also for the same reason, never use floats as loop iterators.
The problem is that most floating point implementation are based on IEEE 754. See http://en.wikipedia.org/wiki/IEEE_floating_point
The problem with this is, that numbers are builded with base 2 (binary formats).
The number 9.9 can never be build with base 2 excatly.
The "Numerical Computation Guide" by David Goldberg gves an exact statement about it:
Several different representations of real numbers have been proposed,
but by far the most widely used is the floating-point representation.
Floating-point representations have a base b (which is always assumed to
be even) and a precision p. If b = 10 and p = 3, then the number 0.1 is
represented as 1.00 × 10^-1. If b = 2 and p = 24, then the decimal
number 0.1 cannot be represented exactly, but is approximately
1.10011001100110011001101 × 2^-4.
You can safely assume two floating point numbers are never equal 'exactly' (unless one is a copy of the other).
Computer works on binary and floating point, in other words in base 2. Just like base 10, base 2 have numbers that it cannot build. For example, try to write the fraction 10/3 in base 10. You'll end up with infinite 3s. and in Binary, you cannot even write 0.1 (decimal) in binary, you'll also get a recurring pattern 0.0001100110011... (binary).
This video will do better to explain http://www.youtube.com/watch?v=PZRI1IfStY0