I try to solve a math problem and my output sensitivity has a little different such as 0.07. And then I compare pow() and powf() in my code and I see this sensitivity. The code as follows:
int main()
{
int terms, sign=-1;
double x, operation=0.0;
printf("Please enter the number of terms : ");
scanf_s("%d", &terms);
while (terms <= 0)
{
printf("Please re-enter the number of terms :");
scanf_s("%d", &terms);
}
printf("Please enter a value for x :");
scanf_s("%lf", &x);
for (int i = 1; i <= terms; i++)
{
sign = sign * (-1);
operation = operation + sign * powf(x + i / 10.0, (2 * i) - 1) / (2 * i);
}
printf("The result is : %.2lf\n", operation);
system("pause");
return 0;
}
Sample:
terms : 10
x : 1.1
output : `-59783.61` with `powf`
output : `-59783.67` with `pow`
What is the difference between to these functions?
pow operates on doubles. powf operates on floats. This is a fairly standard notation in C, where the base name of a function will be for operands (and return values) of the default type (like int and double), while prefixed and suffixed versions are for other types (like long, float, etc). Here is a reference: http://pubs.opengroup.org/onlinepubs/9699919799/.
This difference in data types fully explains the differences you see in your result.
doubles contain 53 bits of precision in the mantissa, which translates to ~16 decimal digits of precision. This exceeds the precision with which you display your result, so is probably accurate enough for your purposes.
floats, on the other hand, have only 24 bits in the mantissa, which translates to ~7 decimal digits. Any combination of operations will cause roundoff errors do creep in almost immediately to within your display precision.
The C language did not have "generic functions" until C11. Instead, there are different functions in the standard library for different data types.
The *f functions of <math.h> operate on single-precision floating point numbers (floats using single precision internally. double stands for ... double precision. Always use the non-f functions for double arguments.
As said here , pow takes a double, where powf takes a float rendering it much less precise.
powf returns and takes arguments of float.
pow returns double and takes arguments of double. If a float number is given as parameter, it is converted to double by the usual promotion rules.See here
The difference you are seeing in the result is due to the higher precision of double
The difference is :
float powf( float base, float exponent );
double pow( double base, double exponent );
DESCRIPTION in here
The pow functions compute base raised to the power of exponent.
Related
I'm creating a simple program which will check whether the value of sin and cosine of an angle is equal to 1 or not i typed this code
#include <stdio.h>
#include <math.h>
int main()
{
int x;
printf("Enter the value of angle in degree: \n");
scanf("%d",&x);
double rad = 0.0174533*x;
double sum = pow(sin(rad),2) + pow(cos(rad),2);
printf("%f",sum);
if (sum == 1)
printf("\nsum of squares of sine and cosine is equal to 1");
else
printf("\nsum of squares of sine and cosine is not equal to
1");
return 0;
and it says the sum is not equal to 1 that is the else block is executed while if i change the code to
#include <stdio.h>
#include <math.h>
int main()
{
int x;
printf("Enter the value of angle in degree: \n");
scanf("%d",&x);
double rad = angle*3.14/180;
double sum = pow(sin(rad),2) + pow(cos(rad),2);
printf("%f",sum);
if (sum == 1)
printf("\nsum of squares of sine and cosine is equal to 1");
else
printf("\nsum of squares of sine and cosine is not equal to 1");
return 0;
It works fine how??
There are two reasons that calculating the sum of the squares of the sine and the cosine of an angle using floating-point arithmetic may not produce exactly 1:
Floating-point arithmetic only approximates real arithmetic. Since a floating-point format can only represent certain values, the real-number result of any mathematical operation is rounded to the nearest value representable in the floating-point format.
Calculating sine, cosine, and exponentiation is somewhat hard, and the implementations of the sin, cos, and pow routines may have errors (greater than those necessitated by the floating-point format).
Those issues cause errors in the arithmetic. Those errors might or might not cancel out, so the final result might or might not be 1.
When formatting a floating-point number using %f, the default precision is six digits after the decimal point. To see the difference between 1 and the representable values closest to 1 in the double format, you need 16 digits after the decimal place. (This assumes the IEEE-754 basic 64-bit binary format is being used for double, which is very common.) In general, you need 17 significant digits to uniquely distinguish the specific value. (This number is given by DBL_DECIMAL_DIG, defined in <float.h>.)
If you format the numbers with printf("%.16f", sum);, you will see the differences.
Although the variations due to rounding can be analyzed, they often behave similarly to random fluctuations. So slight changes in the arithmetic used can cause different results. In this case, the difference between 0.0174533 and 3.14/180 caused the angle to be slightly different, which resulted in slightly different calculations.
Probably when you use
double rad = 0.0174533*x
double sum = pow(sin(rad),2) + pow(cos(rad),2);
printf("%f",sum);
due to the precision of the multiplication with x the value of sum won't be exactly 1.
When you use
printf("%f",sum);
you see 1 because the default precision when printing a float is 6 decimal digits, if sum has more than those it gets truncated. This means that 1.00000001 or 0.9999999 will be both printed as 1 but the if check will fail because they are not actually equal to 1.
To print the float with an higher precision you can use the formula:
printf( "%1.12lf", sum );
where the first 1 after the % is the number of digits in the integer part of the number while the value after the . is the number of digits you want in the decimal part.
I know that by default in C when you declare a float it gets automatically saved as a double and that if you want it to be saved as a float you have to declare it like this
float x = 0.11f
but what if my x value comes from a scanf? How can I do so that when I print it it doesn't get rounded down or up?
Here's my code btw, thanks for the help.
#include <stdio.h>
int main() {
float number = 0;
float comparison;
do{
printf("\nEnter a number: ");
scanf("%f", &comparison);
if(comparison > number) {
number = comparison;
}
}while(comparison > 0);
printf("The largest number enteres was: %f\n\n", number);
}
what if my x value comes from a scanf? How can I do so that when I print it it doesn't get rounded down or up?
scanf with an %f directive will read the input and convert it to a float (not a double). If the matched text does not correspond to a number exactly representable as a float then there will be rounding at this stage. There is no alternative.
When you pass an argument of type float to printf() for printing, it will be promoted to type double. This is required by the signature of that function. But type double can exactly represent all values of type float, so this promotion does not involve any rounding. printf's handling of the %f directives is aligned with this automatic promotion: the corresponding (promoted) argument is expected to be of type double.
There are multiple avenues to reproducing the input exactly, depending on what constraints you are willing to put on that input. The most general is to read, store, and print the data as a string, though even this has its complications.
If you are willing to place a limit on the maximum decimal range and precision for which verbatim reproduction is supported, then you may be able to get output rounded to the same representation as the input by specifying a precision in your printf field directives:
float f;
scanf("%f", &f);
printf("%f %.2f %5.2f\n", f, f, f);
If you want to use a built-in floating-point format and also avoid trailing zeroes being appended then either an explicit precision like that or a %g directive is probably needed:
printf("%f %g\n", f, f);
Other alternatives are more involved, such as creating a fixed-point or arbitrary-precision decimal data type, along with appropriate functions for reading and writing it. I presume that goes beyond what you're presently interested in doing.
Note: "double" is short for "double precision", as opposed to notionally single-precision "float". The former is the larger type in terms of storage and representational capability. In real-world implementations, there is never any "rounding down" from float to double.
Attempting to divide two floats in C, using the code below:
#include <stdio.h>
#include <math.h>
int main(){
float fpfd = 122.88e6;
float flo = 10e10;
float int_part, frac_part;
int_part = (int)(flo/fpfd);
frac_part = (flo/fpfd) - int_part;
printf("\nInt_Part = %f\n", int_part);
printf("Frac_Part = %f\n", frac_part);
return(0);
}
To this code, I use the commands:
>> gcc test_prog.c -o test_prog -lm
>> ./test_prog
I then get this output:
Int_Part = 813.000000
Frac_Part = 0.802063
Now, this Frac_part it seems is incorrect. I have tried the same equation on a calculator first and then in Wolfram Alpha and they both give me:
Frac_Part = 0.802083
Notice the number at the fifth decimal place is different.
This may seem insignificant to most, but for the calculations I am doing it is of paramount importance.
Can anyone explain to me why the C code is making this error?
When you have inadequate precision from floating point operations, the first most natural step is to just use floating point types of higher precision, e.g. use double instead of float. (As pointed out immediately in the other answers.)
Second, examine the different floating point operations and consider their precisions. The one that stands out to me as being a source of error is the method above of separating a float into integer part and fractional part, by simply casting to int and subtracting. This is not ideal, because, when you subtract the integer part from the original value, you are doing arithmetic where the three numbers involved (two inputs and result) have very different scales, and this will likely lead to precision loss.
I would suggest to use the C <math.h> function modf instead to split floating point numbers into integer and fractional part. http://www.techonthenet.com/c_language/standard_library_functions/math_h/modf.php
(In greater detail: When you do an operation like f - (int)f, the floating point addition procedure is going to see that two numbers of some given precision X are being added, and it's going to naturally assume that the result will also have precision X. Then it will perform the actual computation under that assumption, and finally reevaluate the precision of the result at the end. Because the initial prediction turned out not to be ideal, some low order bits are going to get lost.)
Float are single precision for floating point, you should instead try to use double, the following code give me the right result:
#include <stdio.h>
#include <math.h>
int main(){
double fpfd = 122.88e6;
double flo = 10e10;
double int_part, frac_part;
int_part = (int)(flo/fpfd);
frac_part = (flo/fpfd) - int_part;
printf("\nInt_Part = %f\n", int_part);
printf("Frac_Part = %f\n", frac_part);
return(0);
}
Why ?
As I said, float are single precision floating point, they are smaller than double (in most architecture, sizeof(float) < sizeof(double)).
By using double instead of float you will have more bit to store the mantissa and the exponent part of the number (see wikipedia).
float has only 6~9 significant digits, it's not precise enough for most uses in practice. Changing all float variables to double (which provides 15~17 significant digits) gives output:
Int_Part = 813.000000
Frac_Part = 0.802083
So, I am reading a C prog. book and I read this exercise:
Write a program which asks the user to enter a dollars-and-cents amount, then displays the amount with 5% added?
Solution :
#include <stdio.h>
int main(void) {
float original_amount;
printf("Enter an amount: ");
scanf("%f", &original_amount);
printf("With tax added: $%.2f\n", original_amount * 1.05f);
return 0;
}
I know what .3f means (there should be 3 digits after...), but what does 1.05f mean?
The 1.05f does denote a floating point number with value approximately 1.05 (which is 105% = 100% + 5%). The %.2f is a format specifier and is something very different.
The multiplication with this number actually adds 5% to the value (value * 1.05 = value * (100% + 5%) = value + value * 5%).
Format specifiers occur in the first parameter of printf-like functions and tell the function how to output the argument corresponding to its position.
1.05f is a float type that has value 1.05
The program is apparently using multiplication by 1.05f as a way to add 5% to a number. But, because of representation error 1.05f is not exactly 1.05; it's a single-precsion floating point number close† to 1.05.
The float value closest to 1.05 is 1.0499999523162841796875 (assuming the usual 32-bit float format). Since you round the results you would have to use some fairly big numbers to see the effects of the error; try entering 100000000 when the program asks for amount:
Enter an amount: 100000000
With tax added: $104999992.00
If you used double precision instead of single precision, that is, double instead of float and 1.05 instead of 1.05f, the representation error would be smaller but it would still not be exactly 1.05, since this number cannot be represented exactly as the binary floating point numbers that our computers use.
You would get a correct result for 100000000, but still "incorrect" results for astronomically big numbers.
†) How close? From the standard:
For decimal floating constants, and also for
hexadecimal floating constants when
FLT_RADIX
is not a power of 2, the result is either
the nearest representable value, or the larger or smaller representable value immediately
adjacent to the nearest representable value, chosen in an implementation-defined manner.
It's the 5% part of your exercice. It's equal to: original_amout + (original_amout * 5.0 / 100.0).
it means 1.05 as float float you can take the f away it should work
printf has the prototype as int printf(const char *restrict format, ...);, it uses the const char *restrict format string to format the data printed.
You are confused between the format specifier %.2f which is passed as the 1st parameter to printf and the 1.05f passed as part of argument list. As you point out, first one is used for formatting. The argument list 1.05f is used for calculation purposes.The f indicates to the compiler you want to use a float or else by default it will be considered double datatype and the result of original_amount * 1.05f will be stored in a double.
It is sufficient to use a float when you know the number would fit in the float range.And to indicate this, you append a f to numbers in the argument list
Can someone explain me how to choose the precision of a float with a C function?
Examples:
theFatFunction(0.666666666, 3) returns 0.667
theFatFunction(0.111111111, 3) returns 0.111
You can't do that, since precision is determined by the data type (i.e. float or double or long double). If you want to round it for printing purposes, you can use the proper format specifiers in printf(), i.e. printf("%0.3f\n", 0.666666666).
You can't. Precision depends entirely on the data type. You've got float and double and that's it.
Floats have a static, fixed precision. You can't change it. What you can sometimes do, is round the number.
See this page, and consider to scale yourself by powers of 10. Note that not all numbers are exactly representable as floats, either.
Most systems follow IEEE-754 floating point standard which defines several floating point types.
On these systems, usually float is the IEEE-754 binary32 single precision type: it has 24-bit of precision. double is the binary64 double precision type; it has 53-bit of precision. The precision in bit numbers is defined by the IEEE-754 standard and cannot be changed.
When you print values of floating point types using functions of the fprintf family (e.g., printf), the precision is defined as the maximum number of significant digits and is by default set to 6 digits. You can change the default precision with a . followed by a decimal number in the conversion specification. For example:
printf("%.10f\n", 4.0 * atan(1.0)); // prints 3.1415926536
whereas
printf("%f\n", 4.0 * atan(1.0)); // prints 3.141593
It might be roughly the following steps:
Add 0.666666666 with 0.0005 (we get 0.667166666)
Multiply by 1000 (we get 667.166666)
Shift the number to an int (we get 667)
Shift it back to float (we get 667.0)
Divide by 1000 (we get 0.667)
Thank you.
Precision is determined by the data type (i.e. float or double or long double).
If you want to round it for printing purposes, you can use the proper format specifiers in printf(), i.e.
printf("%0.3f\n", 0.666666666) //will print 0.667 in c
Now if you want to round it for calculating purposes you have to first multiply the float by 10^number of digits then typecast to int , do the calculation and then again typecast to float and divide by same power of 10
float f=0.66666;
f *= 1000; // 666.660
int i = (int)f; // 666
i = 2*i; // 1332
f = i; // 1332
f /= 1000; // 1.332
printf("%f",f); //1.332000