-2.6 to the power of 0.2 outputs #IND00 - c

currently i'm doing my practice for C language and i've found one question about function pow() in C\C++.
#include <stdio.h>
#include <math.h>
int main(){
double k = 0.2;
printf("2.6^k = %f\n", pow(2.6, k));
printf("-2.6^k = %f\n", pow(-2.6, k));
}
OUTPUT:
2.6^k = 1.210583
-2.6^k = -1.#IND00
In this example -2.6 to the power of 0.2 i̶s̶ ̶n̶o̶t̶ ̶e̶v̶e̶n̶ ̶a̶ ̶c̶o̶m̶p̶l̶e̶x̶ ̶n̶u̶m̶b̶e̶r̶(Edit: it is),but output says(as i think) that number is indeterminable.
And in my practice there is the following:
image
I implemented this like that:
/* e = 2.1783; x = -2.6 */
result = pow(cos(pow(x,0.2) - pow(e,-x + sqrt(3))) + 1.61,2);
But due to (-x + sqrt(3)) being negative number it outputs:
-1.#IND00

The value 0.2 cannot be represented exactly in binary floating point. So what you have is not actually 0.2 but a value slightly more than that. This yields a complex result so pow returns NaN.
Reading into this further, section 7.12.7.4 of the C standard regarding the pow function states:
double pow(double x, double y);
A domain error occurs if x is finite
and negative and y is finite and not an integer value.
In the event of a domain error, an implementation-defined value is returned. While MSVC doesn't seem to document what it does in this case, it apparently returns NaN. In the case of Linux, the man pages explicitly state that NaN is returned in this case.

With complex number math, -2.60.2 is 0.979382 +0.711563*i.
pow(-2.6, k) does not have a real answer.
Alternative: use complex math:
#include <complex.h>
#include <math.h>
#include <stdio.h>
int main(void) {
double k = 0.2;
printf("2.6^k = %f\n", pow(2.6, k));
complex double y = cpow(-2.6, k);
printf("-2.6^k = %f %f*i\n", creal(y), cimag(y));
}
Output
2.6^k = 1.210583
-2.6^k = 0.979382 0.711563*i

Related

Return zero and Inf values in C

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;
}

How to pass infinity values to a function and test the result

I have this function:
#include <complex.h>
complex double f(complex double x, complex double y) {
return x*y;
}
I would like to call it with x = inf + i inf and y = i inf and see what the result is. In particular I want to test if the result is an infinity value (as it should be) or if it is NaN + iNaN. The reason for this is to test different C compilers.
How do you do this in C?
I would add an intermediate check, too:
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#include <math.h>
complex double f(complex double x, complex double y) {
return x*y;
}
int main(void){
complex double x = INFINITY + INFINITY * I;
complex double y = 0.0 + INFINITY * I;
complex double ret;
printf("x = %g + %g*I\n", creal(x), cimag(x));
printf("y = %g + %g*I\n", creal(y), cimag(y));
ret = f(x,y);
printf("f = %g + %g*I\n", creal(ret), cimag(ret));
exit(EXIT_SUCCESS);
}
Why?
Result with gcc-4.9.real (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4
x = nan + inf*I
y = nan + inf*I
f = -inf + -nan*I
Result with Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)
x = nan + inf*I
y = nan + inf*I
f = nan + nan*I
A complete and utter failure from the get go.
I'm not 100% sure this is correct since I've never worked with complex numbers in C, but I've tried this snippet:
#include <stdio.h>
#include <math.h>
#include <complex.h>
double complex f(double complex x, double complex y) {
return x*y;
}
int main(void)
{
double complex z1 = INFINITY + INFINITY * I;
double complex z2 = INFINITY + INFINITY * I;
complex double result = f(z1, z2);
printf("%f + i%f\n", creal(result), cimag(result));
}
I used both clang 3.8 (C 11) and GCC 6.1 (C 11) and the result was:
-inf + i-nan
Based on http://en.cppreference.com/w/c/numeric/math/INFINITY.
Apparently the macro INFINITY is not always supported and thus defined. Check the link above for more info.
You can specify what is basically a complex literal using multiplication with the I macro (which also has a _Complex_I alias). A minor example creating such a value is seen below:
#include <math.h>
#include <complex.h>
int main()
{
complex c = INFINITY * I + INFINITY;
}
The function, as written, is fine, the problem is with the way the complex numbers with special values are created and interpreted.
If you just write
double complex z1 = I * INFINITY;
double complex z2 = INFINITY + I * INFINITY;
you may discover that most of the popular compilers today do not support C99's imaginary numbers, and this expression actually multiplies (0,1) by (inf,0) and then adds (inf,0) to the result.
With gcc, I get z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
with clang, I get z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
with icc, I get z1 = (-nan, inf), z2 = (-nan, inf), f(z1, z2) = (-nan, -nan)
The only compiler that defines I as a pure imaginary number that I have access to is the C compiler from Oracle Studio
with oracle studio, I get z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)
Now this is not actually supposed to be a problem because in C, there is only one Complex Infinity, and every complex number whose one component is infinite is considered to be that infinity, even if the other component is NaN. All built-in arithmetic is supposed to honor that: so in my list above, only Intel appears to have a bug here where multiplication of two complex infinities gave a complex nan.
For the lazy compilers, C11 has a macro that saves the day: CMPLX
double complex z1 = CMPLX(0, INFINITY);
double complex z2 = CMPLX(INFINITY, INFINITY);
now,
with gcc, I get z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)

Why is the function floor giving different results in this case?

In this example, the behaviour of floor differs and I do not understand why:
printf("floor(34000000.535 * 100 + 0.5) : %lf \n", floor(34000000.535 * 100 + 0.5));
printf("floor(33000000.535 * 100 + 0.5) : %lf \n", floor(33000000.535 * 100 + 0.5));
The output for this code is:
floor(34000000.535 * 100 + 0.5) : 3400000053.000000
floor(33000000.535 * 100 + 0.5) : 3300000054.000000
Why does the first result not equal to 3400000054.0 as we could expect?
double in C does not represent every possible number that can be expressed in text.
double can typically represent about 264 different numbers. Neither 34000000.535 nor 33000000.535 are in that set when double is encoded as a binary floating point number. Instead the closest representable number is used.
Text 34000000.535
closest double 34000000.534999996423...
Text 33000000.535
closest double 33000000.535000000149...
With double as a binary floating point number, multiplying by a non-power-of-2, like 100.0, can introduce additional rounding differences. Yet in these cases, it still results in products, one just above xxx.5 and another below.
Adding 0.5, a simple power of 2, does not incurring rounding issues as the value is not extreme compared to 3x00000053.5.
Seeing intermediate results to higher print precision well shows the typical step-by-step process.
#include <stdio.h>
#include <float.h>
#include <math.h>
void fma_test(double a, double b, double c) {
int n = DBL_DIG + 3;
printf("a b c %.*e %.*e %.*e\n", n, a, n, b, n, c);
printf("a*b %.*e\n", n, a*b);
printf("a*b+c %.*e\n", n, a*b+c);
printf("a*b+c %.*e\n", n, floor(a*b+c));
puts("");
}
int main(void) {
fma_test(34000000.535, 100, 0.5);
fma_test(33000000.535, 100, 0.5);
}
Output
a b c 3.400000053499999642e+07 1.000000000000000000e+02 5.000000000000000000e-01
a*b 3.400000053499999523e+09
a*b+c 3.400000053999999523e+09
a*b+c 3.400000053000000000e+09
a b c 3.300000053500000015e+07 1.000000000000000000e+02 5.000000000000000000e-01
a*b 3.300000053500000000e+09
a*b+c 3.300000054000000000e+09
a*b+c 3.300000054000000000e+09
The issue is more complex then this simple answers as various platforms can 1) use higher precision math like long double or 2) rarely, use a decimal floating point double. So code's results may vary.
Question has been already answered here.
In basic float numbers are just approximation. If we have program like this:
float a = 0.2 + 0.3;
float b = 0.25 + 0.25;
if (a == b) {
//might happen
}
if (a != b) {
// also might happen
}
The only guaranteed thing is that a-b is relatively small.

How do I force 0.0/0.0 to return zero instead of NaN in MIPSPro C compiler?

As the question states, I am using the MIPSPRo C compiler, and I have an operation that will return NaN for some data sets where both the numerator and denom are zero. How do I keep this from happening?
On SGI systems with the MIPSPro compiler, you can set the handling of various floating point exceptions with great precision using the facilities in sigfpe.h. As it happens, the division of zero by zero is one such case:
#include <stdio.h>
#include <sigfpe.h>
int main (void) {
float x = 0.0f;
(void) printf("default %f / %f = %f\n", x, x, (x / x));
invalidop_results_[_ZERO_DIV_ZERO] = _ZERO;
handle_sigfpes(_ON, _EN_INVALID, 0, 0, 0);
(void) printf("handled %f / %f = %f\n", x, x, (x / x));
return 0;
}
In use:
arkku#seven:~/test$ cc -version
MIPSpro Compilers: Version 7.3.1.3m
arkku#seven:~/test$ cc -o sigfpe sigfpe.c -lfpe
arkku#seven:~/test$ ./sigfpe
default 0.000000 / 0.000000 = nan0x7ffffe00
handled 0.000000 / 0.000000 = 0.000000
As you can see, setting the _ZERO_DIV_ZERO result changes the outcome of the same division. Likewise you can handle regular division by zero (e.g. if you don't want infinity as the result).
Of course, none of this is standard; it would be more portable to check for NaN after each division and even better to check for zeros before. C99 offers some control over the floating point environment in fenv.h, but I don't think anything suitable for this is available. In any case my old MIPSPro doesn't support C99.
Use an if clause? Also I'm curious why you'd want to ignore this mathematical impossibility. You sure your input isn't wrong/meaningless in this case?
If you don't mind introducing a small error, you can add a small value to the denominator, assuming you are doing floating point arithmetic. apparently has some small values defined:
DBL_MIN is the smallest double
DBL_EPSILON is the smallest double s.t. x+DBL_EPSILON != x
So I would try
#include <float.h>
#define EPS DBL_MIN
double divModified(double num, double denom) {
return num / (denom + EPS);
}
IEEE 754 (the spec for floating point) says that 0.0/0.0 is not a number, i.e. NaN. If you want it to be anything else, by far the best approach is to detect when the operands are both zero in an if clause and return the value that you'd rather give. Perhaps like this:
#define WonkyDiv(a,b) ((a)==0.0&&(b)==0.0 ? 0.0 : (a)/(b))
float wonkyResult = WonkyDiv(numerator, denominator);

Is there a function to round a float in C or do I need to write my own?

Is there a function to round a float in C or do I need to write my own?
float conver = 45.592346543;
I would like to round the actual value to one decimal place, conver = 45.6.
As Rob mentioned, you probably just want to print the float to 1 decimal place. In this case, you can do something like the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float conver = 45.592346543;
printf("conver is %0.1f\n",conver);
return 0;
}
If you want to actually round the stored value, that's a little more complicated. For one, your one-decimal-place representation will rarely have an exact analog in floating-point. If you just want to get as close as possible, something like this might do the trick:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float conver = 45.592346543;
printf("conver is %0.1f\n",conver);
conver = conver*10.0f;
conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
conver = conver/10.0f;
//If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
//conver = roundf(conver*10.0f)/10.0f;
printf("conver is now %f\n",conver);
return 0;
}
I doubt this second example is what you're looking for, but I included it for completeness. If you do require representing your numbers in this way internally, and not just on output, consider using a fixed-point representation instead.
Sure, you can use roundf(). If you want to round to one decimal, then you could do something like: roundf(10 * x) / 10
#include <math.h>
double round(double x);
float roundf(float x);
Don't forget to link with -lm. See also ceil(), floor() and trunc().
Just to generalize Rob's answer a little, if you're not doing it on output, you can still use the same interface with sprintf().
I think there is another way to do it, though. You can try ceil() and floor() to round up and down. A nice trick is to add 0.5, so anything over 0.5 rounds up but anything under it rounds down. ceil() and floor() only work on doubles though.
EDIT: Also, for floats, you can use truncf() to truncate floats. The same +0.5 trick should work to do accurate rounding.
To print a rounded value, #Matt J well answers the question.
float x = 45.592346543;
printf("%0.1f\n", x); // 45.6
As most floating point (FP) is binary based, exact rounding to one decimal place is not possible when the mathematically correct answer is x.1, x.2, ....
To convert the FP number to the nearest 0.1 is another matter.
Overflow: Approaches that first scale by 10 (or 100, 1000, etc) may overflow for large x.
float round_tenth1(float x) {
x = x * 10.0f;
...
}
Double rounding: Adding 0.5f and then using floorf(x*10.0f + 0.5f)/10.0 returns the wrong result when the intermediate sum x*10.0f + 0.5f rounds up to a new integer.
// Fails to round 838860.4375 correctly, comes up with 838860.5
// 0.4499999880790710449 fails as it rounds to 0.5
float round_tenth2(float x) {
if (x < 0.0) {
return ceilf(x*10.0f + 0.5f)/10.0f;
}
return floorf(x*10.0f + 0.5f)/10.0f;
}
Casting to int has the obvious problem when float x is much greater than INT_MAX.
Using roundf() and family, available in <math.h> is the best approach.
float round_tenthA(float x) {
double x10 = 10.0 * x;
return (float) (round(x10)/10.0);
}
To avoid using double, simply test if the number needs rounding.
float round_tenthB(float x) {
const float limit = 1.0/FLT_EPSILON;
if (fabsf(x) < limit) {
return roundf(x*10.0f)/10.0f;
}
return x;
}
There is a round() function, also fround(), which will round to the nearest integer expressed as a double. But that is not what you want.
I had the same problem and wrote this:
#include <math.h>
double db_round(double value, int nsig)
/* ===============
**
** Rounds double <value> to <nsig> significant figures. Always rounds
** away from zero, so -2.6 to 1 sig fig will become -3.0.
**
** <nsig> should be in the range 1 - 15
*/
{
double a, b;
long long i;
int neg = 0;
if(!value) return value;
if(value < 0.0)
{
value = -value;
neg = 1;
}
i = nsig - log10(value);
if(i) a = pow(10.0, (double)i);
else a = 1.0;
b = value * a;
i = b + 0.5;
value = i / a;
return neg ? -value : value;
}
you can use #define round(a) (int) (a+0.5) as macro
so whenever you write round(1.6) it returns 2 and whenever you write round(1.3) it return 1.

Resources