NaN issue and if statement

I'm having trouble with my code when I add an if condition to check if B_body(3) is less than 1e-5.
Without the if condition, everything works fine.
But when I add the if condition, I get a warning and B_body(3) values become NaN.
I've tried several solutions, but nothing works.
Any ideas on how to fix this?
epsilon=1e-5;
if abs(B_body(3))<epsilon
T_rw=[0;0;0];
else
T_rw = [0; 0; 1] * (B_body' * T_commanded) / (B_body(3));
end

11 Comments

We don't have enough code to know what happens next, but almost certainly what then occurs after the T_rw vector is set to identically zero is that B_body(3) also becomes identically zero and then the first step after that you end up with a case of
0/0
ans = NaN
which is where the NaN comes from. Beyond that, all hope is lost.
You'll need some other special casing to deal with whatever is supposed to happend afterwards, but the model as written doesn't handle the case when whatever T_rw represents becomes identically zero.
But when I add the if condition, I get a warning
What is the full and exact text of the warning message? Please show us all the text displayed in orange in the Command Window. The exact text may be useful and/or necessary to determine what's going on and how to avoid the warning.
If you put your code in your question or a comment, you can run it. That way you can confirm we will see the same error as you.
As others rightly mentioned, looks like the issue might be arising from the division by B_body(3) when it is very close to zero which leads to division by zero which in turn might be the reason for NaNs.
To avoid this, you can add a small value (like delta) to the denominator to prevent division by zero. You can try this out:
epsilon = 1e-5;
delta = 1e-6;
if abs(B_body(3)) < epsilon
T_rw = [0; 0; 0];
else
T_rw = [0; 0; 1] * (B_body' * T_commanded) / (B_body(3) + delta);
end
This approach slightly modifies the calculation, so make sure it still meets your requirements. If precision is crucial, you might need to handle the code more carefully.
I hope this is beneficial to you. If you need further assistance, please feel free to reach out.
"when it is very close to zero which leads to division by zero which in turn might be the reason for NaN"
Dividing zero by zero leads to NaN. Even dividing zero by the nearest value closest to zero (i.e. the smallest subnormal) does not produce NaN:
0/eps(0)
ans = 0
0/0
ans = NaN
Being "very close to zero" is not sufficient.
Thanks you @Stephen23 for clearing that out.
And, just for good measure, anything nonzero divided by 0 produces a signed Inf, not NaN.
eps(0)/0
ans = Inf
realmax/0
ans = Inf
ADDENDUM:
(1)/(-0)
ans = -Inf
(-1/0)
ans = -Inf
(-1)/(-0)
ans = Inf
NOTA BENE: the sign is based on the sign of the quotient; the (-0) in the denominator is also significant. This can be helpful in some branch analyses...
And, just for good measure, anything nonzero divided by 0 produces Inf, not NaN
To be technically correct it produces an infinite value, not necessarily positive Inf.
y = (-1)/0
y = -Inf
There are three non-finite values in MATLAB: Inf, -Inf, and NaN. Those are the values for which the built-in isfinite function will return false, but only the first two will have isinf return true.
x = [1; Inf; -Inf; NaN; 5];
fin = isfinite(x);
infinite = isinf(x);
results = table(x, fin, infinite, VariableNames = ["value", "is finite", "is infinite"])
results = 5x3 table
value is finite is infinite _____ _________ ___________ 1 true false Inf false true -Inf false true NaN false false 5 true false
OK, Steven, you're correct...I didn't mean to imply all would return +Inf...I added the (I thought implied) "signed".... :)
Thank you all for your helpful suggestions and for taking the time to assist me with my question. I think I have finally found a solution that works for my needs.
You don't neceessarily have to divide by zero to get an infinite value, either...anything that would produce a result greater than the magnitude of realmax or less than realmin will do...division, multiplication or a function like an exponential with positive magnitude...
exp(709)
ans = 8.2184e+307
exp(710)
ans = Inf

Sign in to comment.

Answers (0)

Categories

Tags

Asked:

on 7 Aug 2024

Commented:

dpb
on 10 Aug 2024

Community Treasure Hunt

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

Start Hunting!