Setting a lower bound on the values of an array ( can it be done without a for loop?)

26 views (last 30 days)
I have a matrix the values of it are very small, some are so small that they appear as NaN. Is there an efficient way to go through the matrix and whenever a value is so small that its NaN It changes to the smallest number matlab can hold? Moreover, what is the smallest number matlab can hold?
EDIT : Yes I was wrong in what I wrote the values are very small i.e close to zero, so matlab is just calling them zero. I dont want any values to be zero because I want to divide by them later. I wanted to bound the values of my matrix away from zero.

Accepted Answer

John D'Errico
John D'Errico on 12 Oct 2021
Edited: John D'Errico on 12 Oct 2021
Since the question is morphing along, I'll add a second answer to the current question.
You cannot tell MATLAB to automatically never allow a matrix element to become as small as zero.
You CAN test to see if an element has become smaller than some desired value, and then replace it. For example...
format long g
X = [1e-100, 1e-20, 1e-3, 1 10]
X =
1e-100 1e-20 0.001 1 10
minX = 1e-10;
X(X < minX) = minX
X =
1e-10 1e-10 0.001 1 10
The above is trivial to do, thus testing to see if an element is smaller than what I would like, and replacing it with some minimum value.
I could also have just used the max function, thus I might have written:
X = max(X,minX);

More Answers (1)

John D'Errico
John D'Errico on 12 Oct 2021
Edited: John D'Errico on 12 Oct 2021
I'm sorry, but you are simply wrong. When a number is TOO small, it does not turn into a NaN. It turns into either zero, or -inf. Which it is depends on whether you are talking about how near a number is to -infinity or to zero.
For example...
format long g
X = 1;
Y = 1/2;
while X ~= Y
X = Y;
Y = Y/2;
end
[X,Y]
ans = 1×2
0 0
So I kept on dividing by 2, stopping only when an underflow happened, and both values are now zero. Are they EXACTLY zero?
[X,Y] == 0
ans = 1×2 logical array
1 1
So yes. They are EXACTLY zero.
There are many computations that will produce a NaN. NaNs are created where a result is indeterminate. For example, there is no way to consistently define the value 0/0 in an intelligent way using limits. So we say that 0/0 is indeterminate.
0/0
ans =
NaN
SImilarly, we cannot define the ratio of two infinities as anything valid. Nor can we dinfine the difference of two infinities. So we have
inf/inf
ans =
NaN
inf - inf
ans =
NaN
You would also guess that things like sin(inf) have no value we could assign. This is because sin(X) is a periodic function, so as we take a limit, we get nothing meaningful.
sin(inf)
ans =
NaN
But it is NEVER true that a number will be so small as to become NaN.
Could you have a situation where a ratio approaches zero, and then at some point suddenly creates a NaN? Well yes. But this is not because the number was getting too small. For example...
% What is the limit of X/X^2 as X --> inf?
syms X
limit(X/X^2,X,inf)
ans = 
0
MATLAB is smart enough to know this limit to be zero. But now try this:
for n = 1:50:1000
X = 10^n;
disp([n,X/X^2])
end
1 0.1 51 1e-51 101 1e-101 151 1e-151 201 0 251 0 301 0 351 NaN 401 NaN 451 NaN 501 NaN 551 NaN 601 NaN 651 NaN 701 NaN 751 NaN 801 NaN 851 NaN 901 NaN 951 NaN
So the ratio becomes smaller and smaller. Eventually, it becomes 0. And then, suddenly, we get a NaN. WHAT HAPPENED? I thought I just said this cannot happen?
In fact, I was correct. What happened was at the point where X overflowed to inf, then X^2 is also inf. Now MATLAB computes inf/inf, and returns a NaN. The problem was NOT that the ratio was too small, but that the numerator AND the denominator were BOTH infinities. And what did I say inf/inf will produce? Correct: NaN.
Similarly, when numbers approach -infinity, they do not suddeny become NaN. Instead, they become -inf at the point of overflow for a double. But never NaN.
Whatever is producing NaNs, this we cannot guess, since you tell us too little information.
You do ask two other questions. Technically, the smallest number representable in MATLAB is realmin/2^52.
realmin
ans =
2.2250738585072e-308
realmin/2^52
ans =
4.94065645841247e-324
realmin/2^53
ans =
0
Below the level of realmin, we wander into the realm of what are called denormalized numbers. And we can go down a little ways until we get to realmin/2^52. Beyond that we just underflow to 0.
Can you search for NaNs, and then replace them with some small number? Of course. But you cannot tell MATLAB to do this automtically with all arrays, as a matter of normal operation.
X = [1 2 NaN inf]
X = 1×4
1 2 NaN Inf
X(isnan(X)) = realmin
X = 1×4
1.0000 2.0000 0.0000 Inf
The display format shows that third element as 0.000, but it is truly just realmin.
  2 Comments
Steven Lord
Steven Lord on 31 Jan 2023
Technically, the smallest number representable in MATLAB is realmin/2^52.
Technically, that's the smallest positive number. The smallest finite number is -realmax and the smallest number is -Inf.
Another way to write realmin/2^52 is eps(0). This makes sense as eps(0) is the distance from 0 to the next largest number and so 0 + eps(0) is that next largest number.
format longg
x = realmin/2^52
x =
4.94065645841247e-324
y = eps(0)
y =
4.94065645841247e-324
z = -realmax
z =
-1.79769313486232e+308
w = -Inf
w =
-Inf
You can see they (x and y) have the same bit pattern.
format hex
[x; y; z; w]
ans = 4×1
1.0e+00 * 0000000000000001 0000000000000001 ffefffffffffffff fff0000000000000
Checking who's smallest:
w < z % true
ans = logical
1
z < y % true
ans = logical
1
x == y % also true
ans = logical
1

Sign in to comment.

Categories

Find more on Numeric Types in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!