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 comentarios

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.
Steven Lord
Steven Lord el 7 de Ag. de 2024
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.
Rik
Rik el 7 de Ag. de 2024
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.
Sahas
Sahas el 8 de Ag. de 2024
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.
Stephen23
Stephen23 el 8 de Ag. de 2024
Editada: Stephen23 el 8 de Ag. de 2024
"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.
Sahas
Sahas el 8 de Ag. de 2024
Thanks you @Stephen23 for clearing that out.
dpb
dpb el 8 de Ag. de 2024
Editada: dpb el 8 de Ag. de 2024
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
dpb
dpb el 8 de Ag. de 2024
OK, Steven, you're correct...I didn't mean to imply all would return +Inf...I added the (I thought implied) "signed".... :)
Alexandra
Alexandra el 9 de Ag. de 2024
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

Iniciar sesión para comentar.

Respuestas (0)

Categorías

Más información sobre Data Type Identification en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 7 de Ag. de 2024

Comentada:

dpb
el 10 de Ag. de 2024

Community Treasure Hunt

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

Start Hunting!

Translated by