I tried to implement the following calculation:
#include <stdio.h>
#include <math.h>
int main(){
float sum = 0;
int c = -4;
float x1 = 136.67;
float x2 = 2.38;
sum = c / (pow(abs(x1 - x2), 2));
printf("%f %f %f",sum,x1,x2);
return 0;
}
But the value of sum after the execution turns out to be -4. What is wrong?
abs is declared in <stdlib.h>. It takes an int argument and returns an int result.
The missing #include <stdlib.h> is likely to cause problems as well. You're calling abs with a floating-point argument; without a visible declaration, the compiler will probably assume that it takes a double argument, resulting in incorrect code. (That's under C90 rules; under C99 rules, the call is a constraint violation, requiring a compile-time diagnostic.)
You want the fabs function defined in <math.h>.
abs expects an integer, and you are providing a float. It should work if you apply an explicit type cast:
sum = c / (pow(abs((int)(x1 - x2)), 2));
Related
I'm trying to understand something about sin and sinf from math.h.
I understand that their types differ: the former takes and returns doubles, and the latter takes and returns floats.
However, GCC still compiles my code if I call sin with float arguments:
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
int main ()
{
float x, result;
x = 135 / 180 * PI;
result = sin (x);
printf ("The sin of (x=%f) is %f\n", x, result);
return 0;
}
By default, all compiles just fine (even with -Wall, -std=c99 and -Wpedantic; I need to work with C99). GCC won't complain about me passing floats to sin. If I enable -Wconversion then GCC tells me:
warning: conversion to ‘float’ from ‘double’ may alter its value [-Wfloat-conversion]
result = sin (x);
^~~
So my question is: is there a float input for which using sin, like above, and (implicitly) casting the result back to float, will result in a value that is different from that obtained using sinf?
This program finds three examples on my machine:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
float f, f1, f2;
for(i = 0; i < 10000; i++) {
f = (float)rand() / RAND_MAX;
float f1 = sinf(f);
float f2 = sin(f);
if(f1 != f2) printf("jackpot: %.8f %.8f %.8f\n", f, f1, f2);
}
}
I got:
jackpot: 0.98704159 0.83439910 0.83439904
jackpot: 0.78605396 0.70757037 0.70757031
jackpot: 0.78636044 0.70778692 0.70778686
This will find all the float input values in the range 0.0 to 2 * M_PI where (float)sin(input) != sinf(input):
#include <stdio.h>
#include <math.h>
#include <float.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
int main(void)
{
for (float in = 0.0; in < 2 * M_PI; in = nextafterf(in, FLT_MAX)) {
float sin_result = (float)sin(in);
float sinf_result = sinf(in);
if (sin_result != sinf_result) {
printf("sin(%.*g) = %.*g, sinf(%.*g) = %.*g\n",
FLT_DECIMAL_DIG, in, FLT_DECIMAL_DIG, sin_result,
FLT_DECIMAL_DIG, in, FLT_DECIMAL_DIG, sinf_result);
}
}
return 0;
}
There are 1020963 such inputs on my amd64 Linux system with glibc 2.32.
float precision is approximately 6 significant figures decimal, while double is good for about 15. (It is approximate because they are binary floating point values not decimal floating point).
As such for example: a double value 1.23456789 will become 1.23456xxx as a float where xxx are unlikely to be 789 in this case.
Clearly not all (in fact very few) double values are exactly representable by float, so will change value when down-converted.
So for:
double a = 1.23456789 ;
float b = a ;
printf( "double: %.10f\n", a ) ;
printf( "float: %.10f\n", b ) ;
The result in my test was:
double: 1.2345678900
float: 1.2345678806
As you can see the float in fact retained 9 significant figures in this case, but it is by no means guaranteed for all possible values.
In your test you have limited the number of instances of mismatch because of the limited and finite range of rand() and also because f itself is float. Consider:
int main()
{
unsigned mismatch_count = 0 ;
unsigned iterations = 0 ;
for( double f = 0; f < 6.28318530718; f += 0.000001)
{
float f1 = sinf(f);
float f2 = sin(f);
iterations++ ;
if(f1 != f2)
{
mismatch_count++ ;
}
}
printf("%f%%\n", (double)mismatch_count/iterations* 100.0);}
In my test about 55% of comparisons mismatched. Changing f to float, the mismatches reduced to 1.3%.
So in your test, you see few mismatches because of the constraints of your method of generating f and its type. In the general case the issue is much more obvious.
In some cases you might see no mismatches - an implementation may simply implement sinf() using sin() with explicit casts. The compiler warning is for the general case of implicitly casting a double to a float without reference to any operations performed prior to the conversion.
However, GCC still compiles my code if I call sin with float arguments:
Yes, this is because they are implicitly converted to double (because sin() requires a float), and back to float (because sin() returns a double) on entering and exiting from the sinf() function. See below why it is better to use sinf() in this case, instead of having only one function.
You have included math.h which has prototypes for both function calls:
double sin(double);
float sinf(float);
And so, the compiler knows that to use sin() it is necessary a conversion from float to double so it compiles a conversion before calling, and also compiles a conversion from double to float in the result from sin().
In case you have not #include <math.h> and you ignored the compiler warning telling you are calling a function sin() with no prototype, the compiler should have also converted first the float to double (because on nonspecified argument types this is how it mus proceed) and pass the double data to the function (which is assumed to return an int in this case, that will provoke a serious Undefined Behaviour)
In case you have used the sinf() function (with the proper prototype), and passed a float, then no conversion should be compiled, the float is passed as such with no type conversion, and the returned value is assigned to a float variable, also with no conversion. So everything goes fine with no conversion, this makes the fastest code.
In case you have used the sinf() function (with no prototype), and passed a float, this float would be converted to a double and passed as such to sinf(), resulting in undefined behaviour. In case somehow sinf() returned properly, an int result (that could have something to do with the calculation or not, as per UB) would be converted into float type (should this be possible) and assigned to the result value.
In the case mentioned above, in case you are operating on floats, it is better to use sinf() as it takes less to execute (it has less iterations to do, as less precision is required in them) and the two conversions (from float to double and back from double to float) have not to be compiled in, in the binary code output by the compiler.
There are some systems where computations on float are an order of magnitude faster than computations on double. The primary purpose of sinf is to allow trigonometric calculations to be performed efficiently on such systems in cases where the lower precision of float would be adequate to satisfy application needs. Converting a value to float, calling sin, and converting the result to float would always yield a value that either matched that of sinf or was more accurate(*), and on some implementations that would in fact be the most efficient way of implementing sinf. On some other systems, however, such an approach would be more than an order of magnitude slower than using a purpose-designed function to evaluate the sine of a float.
(*) Note that for arguments outside the range +/- π/2, the most mathematically accurate way of computing sin(x) for an exact specified value of x might not be the most accurate way of computing what the calling code wants to know. If an application computes sinf(angle * (2.0f * 3.14159265f)), when angle is 0.5, having the function (double)3.1415926535897932385-(float)3.14159265f may be more "mathematically accurate" than having it return sin(angle-(2.0f*3.14159265f)), but the latter would more accurately represent the sine of the angle the code was actually interested in.
I use C to do computation using the following code:
#include <stdio.h>
#include <math.h>
void main() {
float x = 3.104924e-33;
int i = 6000, j = 1089;
float value, value_inv;
value = sqrt(x / ((float)i * j));
value_inv = 1. / value;
printf("value = %e\n", value);
printf("value_inv = %e\n", value_inv);
}
We can see, in fact, value = 2.18e-20. This does not exceed the boundary of float data type in C. But why the computer gives me
value = 0.000000e+00
value_inv = inf
Does anybody know why it happens and how to solve this problem without changing data type to double?
OP's float apparently does not support sub-normals. C allows non-support.
Does anybody know why it happens and how to solve this problem without changing data type to double?
This may be a implementation detail or due to a compiler option. Without changing to double, look to a different compiler or options. Look at options concerning sub-normal support, precision used for intermediate calculation and optimization levels (which sometimes short edge change cases like this.)
On my machine which does handle sub-normals, using C11, FLT_TRUE_MIN, smallest non-zero float is smaller than FLT_MIN, the smallest normal non-zero float.
#include<float.h>
float xx = x/((float)i*j);
printf("xx = %e %e %e\n",xx, FLT_MIN, FLT_TRUE_MIN);
Output
xx = 4.751943e-40 1.175494e-38 1.401298e-45
In OP's case, without sub-normal support, xx became 0.0f and led to the undesired output.
Using double math will handle the small intermediate float values.
value = sqrt(x/(1.0*i*j)); // Form product with `double` math
value_inv = 1.0f/value; // Here we can just use float math
printf("value = %e\n",value);
printf("value_inv = %e\n",value_inv);
Output
value = 2.179897e-20
value_inv = 4.587373e+19
On my computer (Ryzen 2700X, x86_64) the results are:
value = 2.179897e-020
value_inv = 4.587373e+019
You can try 1.f instead 1. , which actually is a double:
value_inv = 1.f/value;
Apparently your system hasn't support more digit for float. On my system the output is:
value = 2.179895e-020
value_inv = 4.587376e+019
I got the answer by myself.
I should change sqrt(x/((float)i*j)) to sqrt((double)x/((double)i*j)). After this, I can get correct result:
value = 2.179897e-20
value_inv = 4.587373e+19
There is no reason to use float instead of double for such computations:
3.104924e-33 is a double constant, it gets converted to float upon assignment, with a potential loss of precision
sqrt gets a double argument and returns a double value. Implicit conversions occur again with potential loss of precision.
1. / value computes with the type double because 1. has this type. value gets converted before the division and the result is converted to float to store to value_inv.
value and value_inv are implicitly converted to double when passed to printf.
All these conversions may incur loss of precision or even truncation to 0.. You should instead always use double unless there is a strong requirement to use float:
#include <stdio.h>
#include <math.h>
int main() {
double x = 3.104924e-33;
int i = 6000, j = 1089;
double value, value_inv;
value = sqrt(x / ((double)i * j));
value_inv = 1. / value;
printf("value = %e\n", value);
printf("value_inv = %e\n", value_inv);
return 0;
}
If for some reason you are required to use float, be careful to avoid unneeded conversions:
#include <stdio.h>
#include <math.h>
int main() {
float x = 3.104924e-33F;
int i = 6000, j = 1089;
float value, value_inv;
value = sqrtf(x / ((float)i * j));
value_inv = 1.F / value;
printf("value = %e\n", value);
printf("value_inv = %e\n", value_inv);
return 0;
}
This question already has answers here:
Why is my power operator (^) not working?
(11 answers)
Closed 7 years ago.
So in python, all I have to do is
print(3**4)
Which gives me 81
How do I do this in C? I searched a bit and say the exp() function, but have no clue how to use it, thanks in advance
You need pow(); function from math.h header.
syntax
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
Here x is base and y is exponent. result is x^y.
usage
pow(2,4);
result is 2^4 = 16. //this is math notation only
// In c ^ is a bitwise operator
And make sure you include math.h to avoid warning ("incompatible implicit declaration of built in function 'pow' ").
Link math library by using -lm while compiling. This is dependent on Your environment.
For example if you use Windows it's not required to do so, but it is in UNIX based systems.
you can use pow(base, exponent) from #include <math.h>
or create your own:
int myPow(int x,int n)
{
int i; /* Variable used in loop counter */
int number = 1;
for (i = 0; i < n; ++i)
number *= x;
return(number);
}
#include <math.h>
printf ("%d", (int) pow (3, 4));
There's no operator for such usage in C, but a family of functions:
double pow (double base , double exponent);
float powf (float base , float exponent);
long double powl (long double base, long double exponent);
Note that the later two are only part of standard C since C99.
If you get a warning like:
"incompatible implicit declaration of built in function 'pow' "
That's because you forgot #include <math.h>.
For another approach, note that all the standard library functions work with floating point types. You can implement an integer type function like this:
unsigned power(unsigned base, unsigned degree)
{
unsigned result = 1;
unsigned term = base;
while (degree)
{
if (degree & 1)
result *= term;
term *= term;
degree = degree >> 1;
}
return result;
}
This effectively does repeated multiples, but cuts down on that a bit by using the bit representation. For low integer powers this is quite effective.
just use pow(a,b),which is exactly 3**4 in python
Actually in C, you don't have an power operator. You will need to manually run a loop to get the result. Even the exp function just operates in that way only. But if you need to use that function, include the following header
#include <math.h>
then you can use pow().
This question already has answers here:
Why is my power operator (^) not working?
(11 answers)
Closed 7 years ago.
So in python, all I have to do is
print(3**4)
Which gives me 81
How do I do this in C? I searched a bit and say the exp() function, but have no clue how to use it, thanks in advance
You need pow(); function from math.h header.
syntax
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
Here x is base and y is exponent. result is x^y.
usage
pow(2,4);
result is 2^4 = 16. //this is math notation only
// In c ^ is a bitwise operator
And make sure you include math.h to avoid warning ("incompatible implicit declaration of built in function 'pow' ").
Link math library by using -lm while compiling. This is dependent on Your environment.
For example if you use Windows it's not required to do so, but it is in UNIX based systems.
you can use pow(base, exponent) from #include <math.h>
or create your own:
int myPow(int x,int n)
{
int i; /* Variable used in loop counter */
int number = 1;
for (i = 0; i < n; ++i)
number *= x;
return(number);
}
#include <math.h>
printf ("%d", (int) pow (3, 4));
There's no operator for such usage in C, but a family of functions:
double pow (double base , double exponent);
float powf (float base , float exponent);
long double powl (long double base, long double exponent);
Note that the later two are only part of standard C since C99.
If you get a warning like:
"incompatible implicit declaration of built in function 'pow' "
That's because you forgot #include <math.h>.
For another approach, note that all the standard library functions work with floating point types. You can implement an integer type function like this:
unsigned power(unsigned base, unsigned degree)
{
unsigned result = 1;
unsigned term = base;
while (degree)
{
if (degree & 1)
result *= term;
term *= term;
degree = degree >> 1;
}
return result;
}
This effectively does repeated multiples, but cuts down on that a bit by using the bit representation. For low integer powers this is quite effective.
just use pow(a,b),which is exactly 3**4 in python
Actually in C, you don't have an power operator. You will need to manually run a loop to get the result. Even the exp function just operates in that way only. But if you need to use that function, include the following header
#include <math.h>
then you can use pow().
Isn't line 7 of this program "pay = prt(pay);" supposed to throw a compile or run-time error because it is passing in an int to a param that requires a double? I compiled it fine with dev-c++ and ran the program with both lines of output. Please explain, thank you.
#include <stdio.h>
int prt(double b);
main ()
{
int pay = 3;
double tax = 2.2;
pay = prt(pay);
prt(tax);
}
int prt(double b)
{
b *= 2;
printf("%.2lf\n", b);
}
C will automatically convert between different numeric types in this situation.
See Implicit type conversion in C-like languages.
You declared a function as int but never returned anything, and didn't give main a return type either. I'd say any compiler would be well within it's rights to reject your code.
data type having smaller or equal size can be converted to higher one.
in reverse case:
Float to int causes truncation, ie removal of the fractional part.
double to float causes rounding of digit
long int to int causes dropping of excess higher order bits.