This question already has an answer here:
pow() function in C problems [duplicate]
(1 answer)
Closed 3 years ago.
I'm trying to multiply 2, 3 digit numbers.
I used 2 for loops (nested) and multiplied each digit of num1 with num2,
and shifted each result to the appropriate place using pow().
So the problem is pow(10,3) is coming out to be 299 instead of 300.
I haven't tried much as but used printf to find what is actually happening in the runtime and this is what I have found.
the values of tempR after shift should be
5,40,300,100,800,6000,1500,12000,90000
but are coming as
5,40,299,100,799,6000,1500,12000,89999
int main(void)
{
int result; // final result
int tempR; // temporary for each iteration
char a[] = "345"; // number 1
char b[] = "321"; // number 2
for(int i = 2;i>= 0 ; i --)
{
for(int j = 2;j >= 0 ; j --)
{
int shift = abs(i-2 + j -2);
printf("%d\n",shift); //used to see the values of shift.
//and it is coming as expected
tempR = (int)(b[i] - '0') * (int)(a[j] - '0');
printf("%d \n",tempR); // value to tempR is perfect
tempR = tempR*pow(10,shift);
printf("%d \n",tempR); // here the problem starts
result += tempR;
}
}
printf("%d",result);
}
Although IEEE754 (ubiquitous on desktop systems) is required to return the best possible floating point value for certain operators such as addition, multiplication, division, and subtraction, and certain functions such as sqrt, this does not apply to pow.
pow(x, y) can and often is implemented as exp(y * ln (x)). Hopefully you can see that this can cause result to "go off" spectacularly when pow is used with seemingly trivial integral arguments and the result truncated to int.
There are C implementations out there that have more accurate implementations of pow than the one you have, particularly for integral arguments. If such accuracy is required, then you could move your toolset to such an implementation. Borrowing an implementation of pow from a respected mathematics library is also an option, else roll your own. Using round is also a technique, if a little kludgy if you get my meaning.
Never use float functions for the integer calculations. Your pow result almost never will be precise. In this case it is slightly below 300 and the cast to integer makes it 299.
The pow function operates on doubles. Doubles use finite precision. Conversion back to integer chops rather than rounding.
Finite precision is like representing 1/3 as 0.333333. If you do 9 * 1/3 and chop to an integer, you'll get 2 instead of 3 because 9 * 1/3 will give 2.999997 which chops to two.
This same kind of rounding and chopping is causing you to be off by one. You could also round by adding 0.5 before chopping to an integer, but I wouldn't suggest it.
Don't pass integers through doubles and back if you expect exact answers.
Others have mentioned that pow does not yield exact results, and if you convert the result to an integer there's a high risk of loss of precision. Especially since if you assign a float type to an integer type, the result get truncated rather than rounded. Read more here: Is floating math broken?
The most convenient solution is to write your own integer variant of pow. It can look like this:
int int_pow(int num, int e)
{
int ret = 1;
while(e-- > 0)
ret *= num;
return ret;
}
Note that it will not work if e is negative or if both num and e is 0. It also have no protection for overflow. It just shows the idea.
In your particular case, you could write a very specialized variant based on 10:
unsigned int pow10(unsigned int e)
{
unsigned int ret = 1;
while(e-- > 0)
ret *= 10;
return ret;
}
Related
I am new to C, and my task is to create a function
f(x) = sqrt[(x^2)+1]-1
that can handle very large numbers and very small numbers. I am submitting my script on an online interface that checks my answers.
For very large numbers I simplify the expression to:
f(x) = x-1
By just using the highest power. This was the correct answer.
The same logic does not work for smaller numbers. For small numbers (on the order of 1e-7), they are very quickly truncated to zero, even before they are squared. I suspect that this has to do with floating point precision in C. In my textbook, it says that the float type has smallest possible value of 1.17549e-38, with 6 digit precision. So although 1e-7 is much larger than 1.17e-38, it has a higher precision, and is therefore rounded to zero. This is my guess, correct me if I'm wrong.
As a solution, I am thinking that I should convert x to a long double when x < 1e-6. However when I do this, I still get the same error. Any ideas? Let me know if I can clarify. Code below:
#include <math.h>
#include <stdio.h>
double feval(double x) {
/* Insert your code here */
if (x > 1e299)
{;
return x-1;
}
if (x < 1e-6)
{
long double g;
g = x;
printf("x = %Lf\n", g);
long double a;
a = pow(x,2);
printf("x squared = %Lf\n", a);
return sqrt(g*g+1.)- 1.;
}
else
{
printf("x = %f\n", x);
printf("Used third \n");
return sqrt(pow(x,2)+1.)-1;
}
}
int main(void)
{
double x;
printf("Input: ");
scanf("%lf", &x);
double b;
b = feval(x);
printf("%f\n", b);
return 0;
}
For small inputs, you're getting truncation error when you do 1+x^2. If x=1e-7f, x*x will happily fit into a 32 bit floating point number (with a little bit of error due to the fact that 1e-7 does not have an exact floating point representation, but x*x will be so much smaller than 1 that floating point precision will not be sufficient to represent 1+x*x.
It would be more appropriate to do a Taylor expansion of sqrt(1+x^2), which to lowest order would be
sqrt(1+x^2) = 1 + 0.5*x^2 + O(x^4)
Then, you could write your result as
sqrt(1+x^2)-1 = 0.5*x^2 + O(x^4),
avoiding the scenario where you add a very small number to 1.
As a side note, you should not use pow for integer powers. For x^2, you should just do x*x. Arbitrary integer powers are a little trickier to do efficiently; the GNU scientific library for example has a function for efficiently computing arbitrary integer powers.
There are two issues here when implementing this in the naive way: Overflow or underflow in intermediate computation when computing x * x, and substractive cancellation during final subtraction of 1. The second issue is an accuracy issue.
ISO C has a standard math function hypot (x, y) that performs the computation sqrt (x * x + y * y) accurately while avoiding underflow and overflow in intermediate computation. A common approach to fix issues with subtractive cancellation is to transform the computation algebraically such that it is transformed into multiplications and / or divisions.
Combining these two fixes leads to the following implementation for float argument. It has an error of less than 3 ulps across all possible inputs according to my testing.
/* Compute sqrt(x*x+1)-1 accurately and without spurious overflow or underflow */
float func (float x)
{
return (x / (1.0f + hypotf (x, 1.0f))) * x;
}
A trick that is often useful in these cases is based on the identity
(a+1)*(a-1) = a*a-1
In this case
sqrt(x*x+1)-1 = (sqrt(x*x+1)-1)*(sqrt(x*x+1)+1)
/(sqrt(x*x+1)+1)
= (x*x+1-1) / (sqrt(x*x+1)+1)
= x*x/(sqrt(x*x+1)+1)
The last formula can be used as an implementation. For vwry small x sqrt(x*x+1)+1 will be close to 2 (for small enough x it will be 2) but we don;t loose precision in evaluating it.
The problem isn't with running into the minimum value, but with the precision.
As you said yourself, float on your machine has about 7 digits of precision. So let's take x = 1e-7, so that x^2 = 1e-14. That's still well within the range of float, no problems there. But now add 1. The exact answer would be 1.00000000000001. But if we only have 7 digits of precision, this gets rounded to 1.0000000, i.e. exactly 1. So you end up computing sqrt(1.0)-1 which is exactly 0.
One approach would be to use the linear approximation of sqrt around x=1 that sqrt(x) ~ 1+0.5*(x-1). That would lead to the approximation f(x) ~ 0.5*x^2.
This question already has answers here:
Why pow(10,5) = 9,999 in C++
(8 answers)
Closed 2 years ago.
#include <stdio.h>
#include <math.h>
int main()
{
int loop, place_value=0, c = 5;
for(loop = 0; loop < c; loop++)
{
place_value = 0;
place_value = pow(10, loop);
printf("%d \n", place_value);
}
return 0;
}
This code gives
10
99
1000
9999
Why is 99 and 9999 there in 3rd and 5th line instead of 100 and 10000 respectively?
When asking for power normally, it gives right answer.
#include <stdio.h>
#include <math.h>
int main()
{
printf ("%d", (int) pow (10,3 ));
return 0;
}
1000
pow is a difficult routine to implement, and not all implementations give good results. Roughly speaking, the core algorithm for pow(x, y) computes a logarithm from (a part of) x, multiplies it by y, and computes an exponential function on the product. Doing this in floating-point introduces rounding errors that are hard to control.
The result is that the computed result for pow(10, 4) may be something near 10,000 but slightly less or greater. If it is less, than converting it to an integer yields 9999.
When you use arguments hard-coded in source code, the compiler may compute the answer during compilation, possibly using a different algorithm. For example, when y is three, it may simply multiply the first argument by itself, as in x*x*x, rather than using the logarithm-exponent algorithm.
As for why the low result happens with the odd numbers you have tested, consider what happens when we multiply 5.45454545 by various powers of 10 and round to an integer. 5.45454545 rounds down to 5. 54.5454545 rounds up to 55. 545.454545 rounds down to 545. The rounding up or down is a consequence of what fraction happens to land beyond the decimal point. For your cases with pow(10, loop), the bits of the logarithm of 10 may just happen to give this pattern with the few odd numbers you tried.
pow(x, y) function translate more or less to exp(log(x) * y), which will give a result that is not quite the same as x ^ y.
In order to solve this issue you can round this:
round(pow(x, y))
The rule of thumb: never use floating point functions (especially such a complicated ones like pow or log) with integer numbers.
Simply implement integer pow
unsigned intpow(unsigned x)
{
unsigned result = 1;
while(x --) result *= 10;
return result;
}
it will be much faster or even (the fastest one)
int intpow1(unsigned x)
{
const static unsigned vals[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, /* ... */};
#if defined(CHECK_OVERFLOW)
if(x >= sizeof(vals)/ sizeof(vals[0])) return -1;
#endif
return vals[x];
}
I stumbled on one issue while I was implementing in C the given algorithm:
int getNumberOfAllFactors(int number) {
int counter = 0;
double sqrt_num = sqrt(number);
for (int i = 1; i <= sqrt_num; i++) {
if ( number % i == 0) {
counter = counter + 2;
}
}
if (number == sqrt_num * sqrt_num)
counter--;
return counter;
}
– the reason for second condition – is to make a correction for perfect squares (i.e. 36 = 6 * 6), however it does not avoid situations (false positives) like this one:
sqrt(91) = 18.027756377319946
18.027756377319946 * 18.027756377319946 = 91.0
So my questions are: how to avoid it and what is the best way in C language to figure out whether a double number has any digits after decimal point? Should I cast square root values from double to integers?
In your case, you could test it like this:
if (sqrt_num == (int)sqrt_num)
You should probably use the modf() family of functions:
#include <math.h>
double modf(double value, double *iptr);
The modf functions break the argument value into integral and fractional parts, each of
which has the same type and sign as the argument. They store the integral part (in
floating-point format) in the object pointed to by iptr.
This is more reliable than trying to use direct conversions to int because an int is typically a 32-bit number and a double can usually store far larger integer values (up to 53 bits worth) so you can run into errors unnecessarily. If you decide you must use a conversion to int and are working with double values, at least use long long for the conversion rather than int.
(The other members of the family are modff() which handles float and modfl() which handles long double.)
This question already has answers here:
Strange behaviour of the pow function
(5 answers)
Closed 7 years ago.
I was simply writing a program to calculate the power of an integer. But the output was not as expected. It worked for all the integer numbers except for the power of 5.
My code is:
#include <stdio.h>
#include <math.h>
int main(void)
{
int a,b;
printf("Enter the number.");
scanf("\n%d",&a);
b=pow(a,2);
printf("\n%d",b);
}
The output is something like this:
"Enter the number. 2
4
"Enter the number. 5
24
"Enter the number. 4
16
"Enter the number. 10
99
Can't we use pow() function for int data type??
Floating point precision is doing its job here. The actual working of pow is using log
pow(a, 2) ==> exp(log(a) * 2)
Look at math.h library which says:
###<math.h>
/* Excess precision when using a 64-bit mantissa for FPU math ops can
cause unexpected results with some of the MSVCRT math functions. For
example, unless the function return value is stored (truncating to
53-bit mantissa), calls to pow with both x and y as integral values
sometimes produce a non-integral result. ... */
Just add 0.5 to the return value of pow and then convert it to int.
b = (int)(pow(a,2) + 0.5);
So, the answer to your question
Does pow() work for int data type in C?
Not always. For integer exponentiation you could implement your own function (this will work for 0 and +ve exp only):
unsigned uint_pow(unsigned base, unsigned exp)
{
unsigned result = 1;
while (exp)
{
if (exp % 2)
result *= base;
exp /= 2;
base *= base;
}
return result;
}
there is no int based pow. What you are suffering from is floating point truncation.
an int based pow is too constrained (the range of inputs would quickly overflow an int). In many cases int based pow, like in your case where its powers of 2 can be done efficiently other ways.
printf("%a", pow(10, 2)) and see what you get; I expect you'll see you don't quite get 100. Call lround if you want to round instead of truncating.
The C library function double pow(double x, double y)
It takes double type
When i run the following code
/*Program to find the greatest common divisor of two nonnegative integer
values*/
#include <stdio.h>
int main(void){
printf(" n | n^2\n");
printf("-----------------\n");
for(int n = 1; n<11; n++){
int nSquared = n^2;
printf("%i %i\n",n,nSquared);
}
}
The table that gets returned to the terminal displays as follows
n | n^2
-----------------
1 3
2 0
3 1
4 6
5 7
6 4
7 5
8 10
9 11
10 8
why does the "n^2" side generate the wrong numbers? And is there a way to write superscripts and subscripts in C, so I do not have to display "n^2" and can display that side of the column as "n²" instead?
Use pow function from math.h.
^ is the bitwise exclusive OR operator and has to nothing to do with a power function.
The ^ is the XOR operation. You'd either want to use the math.h function "pow", or write your own.
^ is the bitwise xor operator. You should use the pow function declared in the math.h header.
#include <stdio.h>
#include <math.h>
int main(void) {
printf(" n | n^2\n");
printf("-----------------\n");
for(int n = 1; n < 11; n++){
int nSquared = pow(n, 2); // calculate n raised to 2
printf("%i %i\n", n, nSquared);
}
return 0;
}
Include the math library by the flag -lm for gcc compilation.
As others have pointed out, the problem is that ^ is the bitwise xor operator. C has no exponentiation operator.
You're being advised to use the pow() function to compute the square of an int value.
That's likely to work (if you're careful), but it's not the best approach. The pow function takes two double arguments and returns a double result. (There are powf and powl functions that operator on float and long double, respectively.) That means that pow has to be able to handle arbitrary floating-point exponents; for example, pow(2.0, 1.0/3.0) will give you an approximation of the cube root of two.
Like many floating-point operations, pow is subject to the possibility of rounding errors. It's possible that pow(3.0, 2.0) will yield a result that's just slightly less than 9.0; converting that to int will give you 8 rather than 9. And even if you manage to avoid that problem, converting from integer to floating-point, performing an expensive operation, and then converting back to integer is massive overkill. (The implementation might optimize calls to pow with integer exponents, but I wouldn't count on that.)
It's been said (with slight exaggeration) that premature optimization is the root of all evil, and the time spent doing the extra computations is not likely to be noticeable. But in this case there's a way to do what you want that's both simpler and more efficient. Rather than
int nSquared = n^2;
which is incorrect, or
int nSquared = pow(n, 2);
which is inefficient and possibly unreliable, just write:
int nSquared = n * n;