Let a and b be two numbers between 0 and 1.
How to calculate pow(a,10000)/(pow(a,10000)+pow(b,10000))
?
Ex:- This following code gives -nan as output instead of 0.5
double a = 0.5,b = 0.5;
cout<<pow(a,10000)/(pow(a,10000)+pow(b,10000));
Let a and b be two numbers between 0 and 1.
How to calculate pow(a,10000)/(pow(a,10000)+pow(b,10000))
?
Ex:- This following code gives -nan as output instead of 0.5
double a = 0.5,b = 0.5;
cout<<pow(a,10000)/(pow(a,10000)+pow(b,10000));
There is no simple generic solution to your problem. Writing computer programs dealing with very small and/or very big numbers is an "art of science" - often called numerical analysis. Typical tricks involves scaling before calculating.
In your case each pow(..) is rounded to zero because that is the closest representable value to the real result. After that you do 0/(0 + 0) which is NaN, i.e. Not a Number.
You could go for long double:
long double a = 0.5;
long double b = 0.5;
long double c =pow(a,10000);
long double d =pow(b,10000);
cout << c << endl;
cout << d << endl;
cout<<c/(c+d);
which result in:
5.01237e-3011
5.01237e-3011
0.5
but that will only help for " a while". Increasing the power a bit (just an extra zero) and the problem is back.
long double a = 0.5;
long double b = 0.5;
long double c =pow(a,100000);
long double d =pow(b,100000);
cout << c << endl;
cout << d << endl;
cout<<c/(c+d);
0
0
nan
So you need to write a very complicated class yourself or study how this is handle in numerical analysis.
Start here: https://en.wikipedia.org/wiki/Numerical_analysis or https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic
If you know the exp is the same all three place then you can do:
double a = 0.5,b = 0.5;
int exp = 10000;
//cout<<pow(a,exp)/(pow(a,exp)+pow(b,exp)); is the same as:
cout<<1/(1+pow(b/a,exp));
It will work better for most a and b values but don't expect any precision. If a and b just differs a little bit, you'll get 0 (for a less b) or 1 (for b less a). But the NaN part will be solved.
The standard approach for such problems is to work log-space, that is represent each number as ex where x is your standard floating point type:
addition/subtraction (and summation more generally) can be performed using the log-sum-exp trick, i.e.
multiplication/division become addition/subtraction
raising to a power is multiplication by an exponent:
But in your particular case, you're probably better off using the approach suggested at the end of StillLearning's answer
Compilers don't know enough math to be able to simplify complex code like this (the compiler has no idea what pow actually does, it just knows its a function that takes in 1 type and returns another). So it actually has to go through the calculations step by step. Unfortunately, the result is so small that it won't fit into a double. THat's why it returns NAN- you triggered an underflow of the variable.
If you really need to do this (and I'd question why you need that level of accuracy), you'll need to either do some math tricks to work with a non-standard number system (for example, instead of storing dollars you can store pennies- but use a much higher factor) or you can write your own math class and do all of your own math libraries.
Or you can move to a platform like Mathematica or MatLab that's better for this kind of work and has a lot of these type of issues built in.
pow(0.5,10000)
does underflow, in the sense that the true answer is non-zero, but the result will be zero due to inability to express a sufficiently small number in the given format. –
Gamaliel The interval between −fminN and fminN, where fminN is the smallest positive normal floating point value, is called the underflow gap.
(source: en.wikipedia.org/wiki/Arithmetic_underflow ) Actually I didn't know as I considered it "normal rouding" but it seems to be called flush to zero
- my mistake :) - that's why I got the name: –
Lapwing pow
does; it's not just an arbitrary function. For example, many compilers will optimize pow(x,2)
to x*x
. The particular optimization that would be required here, however, is (a) of extremely limited use and (b) would drastically change results (as in this case, from NaN to a finite number). Compilers don't make optimizations that would result in radically different results unless they're explicitly told to do so. –
Bib © 2022 - 2024 — McMap. All rights reserved.
pow(0.5, 10000)
. I doubt fixed point is a solution for such numbers. – Chapela
andb
are the same (0.5), a/b = 1. – Chapel