This question already has an answer here:
How to deal with overflow and underflow?
(1 answer)
Closed 7 years ago.
I have to create a function where I need to square values. I am told that even if the initial value is not too big or is not too small, the value squared might still overflow (returns inf) or underflow (returns 0), and I need to figure out how to prevent that.
My problem is I do not even understand what numbers can cause an overflow when squared when the number itself is not too large.
I thought it might be for the not too small numbers, e.g. 1/3 with repeating decimal numbers, but MATLAB just turns that into 0.3333.
Can someone give me an example of such a number or explain what kind of numbers would cause this?
For underflow, let's consider Planck's constant: 6.626070040e-34
sqrt(6.626070040e-34)
ans =
2.5741e-17
Well, that's apparently not small enough, let's go smaller:
sqrt(6.626070040e-340)
ans =
0
There's your underflow.
Overflow can be seen the same way, just use big numbers:
sqrt(6.626070040e34)
ans =
2.5741e+17
sqrt(6.626070040e340)
ans =
Inf
Underflow means the numbers are too small for MATLAB to handle, overflow means they are too big for MATLAB to handle.
Thanks to #obchardon here are the numbers on my MATLAB R2012a 64bits system:
realmax('double') %//largest allowed double
ans =
1.7977e+308
realmin('double') %//smallest allowed double
ans =
2.2251e-308
Now that we know what the largest possible value is that MATLAB can handle, let's try going below that and square it:
(realmax('double')-10).^2
ans =
Inf
so the number we tried to square here (realmax('double')-10) is allowable by MATLAB, but not squarable.
Related
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
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.
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.
This question already has an answer here:
What is -0.0 in matlab?
(1 answer)
Closed 9 years ago.
I cannot explain this. I have two variables having the same value, yet they are not identical. Can anybody tell me what I'm missing here?
>> y
y =
3.4000
>> x
x =
3.4000
>> y==x
ans =
0
>> whos x
Name Size Bytes Class Attributes
x 1x1 8 double
>> whos y
Name Size Bytes Class Attributes
y 1x1 8 double
It's really puzzling for me and I swear it's not a joke.
It's because of floating point precision. Try
format long g
and then look at x and y again. It's better to compare x-y to some small tolerance value rather than doing an equality test on floating point numbers
You're comparing float values, an activity which doesn't work quite how you think in basically any language, due to how floating-point values are handled by computers.
The solution to this is generally to instead test whether the different between the values is less than some small threshold.
See here for a Matlab-related discussion of this.
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