exponential function with large argument in matlab [duplicate] - matlab

This question already has answers here:
How to compute an exponent in matlab without getting inf?
(3 answers)
Closed 7 years ago.
I've got one problem for a longer time and I'd be really grateful if you could help me somehow...
I have a code in MATLAB (version R2012a) where I compute some exponential functions using MATLAB's fuction exp. This means that I have something like this:
y = exp(x);
However, when this "x" is larger than a certain number, the result ("y") is infinity; when "x" is smaller than a certain number, the result is 0. As said on the MathWorks' website:
Numerical exceptions may happen, when the absolute value of the real
part of a floating-point argument x is large. If ℜ(x) < -7.4*10^8,
then exp(x) may return the truncated result 0.0 (protection against
underflow). If ℜ(x) > 7.4*10^8, then exp(x) may return the
floating-point equivalent RD_INF of infinity.
My problem is quite obvious - my "x" are pretty large so I receive infinities and zeros instead of results I need. My question is - how do I get the real results? Thanks in advance for help!

Use vpa with a string input:
>> exp(1000)
ans =
Inf
>> vpa('exp(1000)')
ans =
1.9700711140170469938888793522433*10^434
Note the result of vpa is of class sym.

A variable in any language is stored in a certain amount of bytes in the computer's memory. The more bytes used to hold a variable type, the more precise of a result that variable can hold. If you are using integers, the biggest type uses 64 bytes and is uint64. This is an unsigned integer (meaning it can only be positive) that can range from 0 to 18,446,744,073,709, 551,615. If you need decimals, try using vpa.

Related

Are certain MATLAB functions only precise to a certain decimal? How precise is MATLAB really?

I am converting a program from MATLAB 2012 to 2016. I've been getting some strange errors, which I believe some of are due to a lack of precision in MATLAB functions.
For instance, I have a timeseries oldTs as such:
Time Data
-----------------------------
1.00000000000000001 1.277032377439511
1.00000000000000002 1.277032378456123
1.00000000000000003 1.277032380112478
I have another timeseries newTs with similar data, but many more rows. oldTs may have half a million rows, whereas newTs could have a million. I want to interpolate the data from the old timeseries with the new timeseries, for example:
interpolatedTs = interp(oldTs.time, oldTs.data, newTs.time)
This is giving me an error: x values must be distinct
The thing is, my x values are distinct. I think that MATLAB may be truncating some of the data, and therefore believing that some of the data is not unique. I found that other MATLAB functions do this:
test = [1.00000000000000001, 1.00000000000000002, 1.0000000000000000003]
unique(test)
ans =
1
test2 = [10000000000000000001, 10000000000000000002, 10000000000000000003]
unique(test2)
ans =
1.000000000000000e+19
MATLAB thinks that this vector only has one unique value in it instead of three! This is a huge issue for me, as I need to maintain the highest level of accuracy and precision with my data, and I cannot sacrifice any of that precision. Speed/Storage is not a factor.
Do certain MATLAB functions, by default, truncate data at a certain nth decimal? Has this changed from MATLAB 2012 to MATLAB 2016? Is there a way to force MATLAB to use a certain precision for a program? Why does MATLAB do this to begin with?
Any light shed on this topic is much appreciated. Thanks.
No, this has not changed since 2012, nor since the very first version of MATLAB. MATLAB uses, and has always used, double precision floating point values by default (8 bytes). The first value larger than 1 that can be represented is 1 + eps(1), with eps(1) = 2.2204e-16. Basically you have less than 16 decimal digits to play with. Your value 1.00000000000000001 is identical to 1 in double precision floating point representation.
Note that this is not something specific to MATLAB, it is a standard that your hardware conforms to. MATLAB simply uses your hardware's capabilities.
Use the variable precision arithmetic from the Symbolic Math Toolbox to work with higher precision numbers:
data = [vpa(1) + 0.00000000000000001
vpa(1) + 0.00000000000000002
vpa(1) + 0.00000000000000003]
data =
1.00000000000000001
1.00000000000000002
1.00000000000000003
Note that vpa(1.00000000000000001) will not work, as the number is first interpreted as a double-precision float value, and only after converted to VPA, but the damage has already been done at that point.
Note also that arithmetic with VPA is a lot slower, and some operations might not be possible at all.

Matlab single to double conversion error [duplicate]

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
Does someone know why casting double() on a single precision floating point number in Matlab (R2016a) changes the last digits? Here is an example:
format 'long'
x=3.2530601; %arbitrary single precision number
x_s=single(x);
x_d=double(x_s);
If I look at the classes and values of the variables, I can see the following:
x and x_d are doubles, x_s is single as expected. The values are:
x=3.253060100000000
x_s=3.2530601
x_d=3.253060102462769
Since the number 3.2530601 can be represented as a double or single precision floating point number, I don't understant why x and x_d are not the same. They are further away than x+eps(x). I thought maybe Matlab tries to work out the double precision x_d by rational fraction approximation, but calling rat(x,16) does not give the same result as x_d. I'm clueless. Does anyone know what is happening here?
There are two closely-related questions (In MATLAB, are variables REALLY double-precision by default? and Why is 24.0000 not equal to 24.0000 in MATLAB?), that you should be aware of, but this isn't quite covered fully by either of them...
When you calculate the decimal equivalent for a given significand and exponent of a floating-point value, you can calculate it out to as many decimal places as you want, but any places beyond the floating-point relative accuracy are ultimately of no real value and are typically not even displayed. However, they seem to come into play here when converting a lower-precision number to a higher-precision number.
Let's look at your value for x_s, both as it is displayed normally (only showing significant digits) and how vpa would display it (with an arbitrary number of digits):
>> x_s = single(3.2530601) % Create a single-precision number
x_s =
single
3.2530601
>> eps(x_s) % Floating-point relative accuracy
ans =
single
2.3841858e-07
>> vpa(x_s, 16) % Show 16 digits of precision, way more than the relative accuracy
ans =
3.253060102462769
>> x_d = double(x_s) % Convert to double-precision
x_d =
3.253060102462769
Look at that! The digits from vpa match the digits gotten when converting to double-precision. It would appear that, when converting from a single to a double, MATLAB calculates the decimal equivalent of the lower-precision value out to the number of digits for the higher-precision value, and uses that to initialize it.

63 is not equal to 2^(log(63)/log(2)) in Matlab [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 6 years ago.
Because of the floating point error 2^(log(63)/log(2)) isn't equal to 63. Check the results below:
format long;
>> 2^(log(63)/log(2))
ans =
63.000000000000014
And unfortunatelly i can't use vpa on a logarithm according to the Matlab documents:
Unlike exact symbolic values, double-precision values inherently
contain round-off errors. When you call vpa on a double-precision
input, vpa cannot restore the lost precision, even though it returns
more digits than the double-precision value. However, vpa can
recognize and restore the precision of expressions of the form p/q,
pĪ€/q, (p/q)1/2, 2q, and 10q, where p and q are modest-sized integers.
So how can i solve this issue ? I have very big numbers like 2^200 and i get very big errors.
Edit: I'm not asking why it is happening. I'm asking how to make this work as 100% accurate so this isn't a duplicate.
The best solution so far:
Unfortunatelly the solution that is suggested by #Sardar_Usama isn't always working as intended. Check the results below:
>> sym(2^(log(2251799813685247)/log(2)))
ans =
2251799813685259
On the other hand
>> 2^(log(vpa(2251799813685247))/log(vpa(2)))
ans =
2.2517998136852470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0*10^0*10^15
is much much more closer to 2251799813685247 = 2^51. It's error is around ~9.491*10^-494 which makes this the best solution so far but there is still some error.
If you cannot use round or vpa, there is a slower way of dealing this, if you have Symbolic Math Toolbox, by creating symbolic numbers . i.e.
a = sym(2^(log(63)/log(2)))
This will give you sym class 63 which you can later convert to double using:
double(a)
This is what you'll get:
>> format long
>> a = sym(2^(log(63)/log(2)))
a =
63
>> double(a)
ans =
63

How to circumvent the extremely small output values? [duplicate]

This question already has an answer here:
Is there any way to increase 'realmax' in MATLAB?
(1 answer)
Closed 7 years ago.
For example in Matlab:
log(exp(-200)
-200
however
log(exp(-2000))
-inf
Naturally the input to the log function is passed as zero as exp(-2000) is insignificant and the log gives -inf. How can I fix this to receive -2000 instead?
If you have the Symbolic Math Toolbox, it's possible to do this with Variable Precision Arithmetic. Use the vpa function and place your mathematical expression as input into vpa wrapped in a string:
>> vpa('log(exp(-2000))')
ans =
-2000.0
However, this will be represented in symbolic format, so it may be prudent to convert back to a numerical value after you're done. Convert this result using double once you perform the calculation:
>> double(vpa('log(exp(-2000))'))
ans =
-2000
It is often possible to rewrite formulas in a way they do not exceed the range of floating point values. In your case, rewriting it would be trivially -2000. A more "real world" example can be found in this question where rewriting successfully avoided the problem.

Matlab floor bug? [duplicate]

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
I think I found a bug in Matlab. My only explanation is, that matlab calculates internally with other values than the ones which are displayed:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(ans)
ans =
3
Displayed code is an output from the Matlab console. calc(x,y) is just an array of double values.
MATLAB uses the standard IEEE floating point form to store a double.
See that if we subtract off a tiny amount from 4, MATLAB still diplays 4 as the result.
>> format long g
>> 4 - eps(2)
ans =
4
In fact, MATLAB stores the number in a binary form. We can see the decimal version of that number as:
>> sprintf('%.55f',4-eps(2))
ans =
3.9999999999999995559107901499373838305473327636718750000
Clearly MATLAB should not display that entire mess of digits, but by rounding the result to 15 digits, we get 4 for the display.
Clearly, the value in calc(1,11) is such a number, represented internally as less than 4 by just a hair too little that it rounds to 4 on display, but it is NOT exactly 4.
NEVER trust the least significant displayed digit of a result in floating point arithmetic.
Edit:
You seem to think that 3.999999999999999 in MATLAB should be less than 4. Logically, this makes sense. But what happens when you supply that number? AH yes, the granularity of a floating point double is larger than that. MATLAB cannot represent it as a number less than 4. It rounds that number UP to EXACTLY 4 internally.
>> sprintf('%.55f',3.9999999999999999)
ans =
4.0000000000000000000000000000000000000000000000000000000
What you got was a value really close to but lower than 4, and even with format long Matlab has to round to the 15th digit to display the number.
Try this:
format long
asd = 3.9999999999999997 %first not-9 #16th digit
will print 4.000000000000000. Anyone who doesn't know the actual value of asd based on what gets visualized would guess it is at least 4, but running
asd >= 4
gives 0, and so floor(asd) returns 3.
So is a matter of how Matlab rounds the displayed output, the true value stored in the variable is less than 4.
UPDATE:
if you go further with the digits, like 18x9:
>> asd = 3.999999999999999999
asd =
4
>> asd == 4
ans =
1
asd becomes exactly 4! (notice it doesn't display 4.000000000000000 anymore) But that's another story, is no more about rounding the number to have a prettier output, but about how the floating point arithmetic works... Real numbers can be represented up to a certain relative precision: in this case the number you gave is so close to 4 that it becomes 4 itself. Take a look to the Python link posted in the comment by #gokcehan, or here.
I won't go over the problem, instead I will offer a solution: Use the single function:
B = single(A) converts the matrix A to single precision, returning that value in B. A can be any numeric object (such as a double). If A is already single precision, single has no effect. Single-precision quantities require less storage than double-precision quantities, but have less precision and a smaller range.
This is only meant to be a fix to this particular issue, so you would do:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(single(ans))
ans =
4