Detect sign change in Matlab
Show older comments
Hi everyone, I have one question. I have two values : prior_value and current_value. Is there any easy way or any function that can be used to detect sign change between this two values? positive to negative or the other way. Thank you.
Accepted Answer
More Answers (2)
Either:
if ~isequal(sign(previous), sign(current))
Or the trivial:
if previos * current < 0
In both cases the 0 must be considered also, e.g. by "<= 0".
8 Comments
K
on 11 Dec 2012
Derek O'Connor
on 11 Dec 2012
if previos * current < 0
is prone to overflow and underflow which wll give the wrong result.
What is wrong with
if sign(previous) == sign(current) ?
Jan
on 11 Dec 2012
@Derek: Nothing is wrong with the comparison of the SIGNs, see my first suggestion. It makes it only harder to handle the cases of zero values.
Derek O'Connor
on 15 Dec 2012
@Jan, you have not answered the first and most important part of my question. Here is what I wrote long ago about this test in a FEX submission of the Bisect zero-finding algorithm:
3. ===== if fa*fx < 0 then etc.
This is a mathematically clever version of
if sign(fa) ~= sign(fx), then etc.
Let fa = 10^(-170) and fx = -10^(-171). They have different signs but
fa*fx = 0 because -10^(-170)*10^(-171) = -10^(-341) underflows to zero.
The (fa*fx < 0) test then gives the wrong result. There are many other cases where this test will fail.
In Matlab:
>> fa = 1e-170; fx = -1e-171; [fa fx fa*fx fa*fx < 0]
ans = 1e-170 -1e-171 0 0
You can see that fa*fx < 0 returns 0 (false) which is false.
Derek O'Connor
on 16 Dec 2012
Edited: Derek O'Connor
on 16 Dec 2012
Here is a clever test of signed zeros:
>> +0 == -0
ans =
1
>> 1/+0 == 1/-0
ans =
0
>>
This is from a reply by a Mathsworker on Newgroup about 2 years ago but I can't find the link to it.
In other words, Matlab does not implement signed zeros according to the IEEE standard, but it implements signed infinities.
Jan
on 16 Dec 2012
@Derek: I cannot follow you. Your question was "What is wrong with if sign(previous) == sign(current) ?". What is the first part? Do you mean the hint, that a*b<0 is prone to errors? If so, I did not see a reason to answer, because this statement was not a question and correct without doubt and I have posted an equivalent test also: Have you seen "~isequal(sign(previous), sign(current))"?
The fact that previos * current < 0 is prone to underflow is important, when you really get values like "10^(-170) and -10^(-171)". But how often does this happen in a real problem?
Therefore I do not understand, what you are talking about. It is documented that Matlab does not support signed zeros and how are signed infinities connected to the original question? Do you want to stress, that the sign change in [inf, -inf] cannot be detected by the multiplication method? If so, there is no doubt about that.
Derek O'Connor
on 18 Dec 2012
Edited: Derek O'Connor
on 18 Dec 2012
@Jan, the statement ``if previos * current < 0 is prone to overflow and underflow which will give the wrong result'', contains an implicit question: do you recommend a statement that is prone to overflow and underflow which will give the wrong result? Sorry for the idiomatic English.
Your argument ``But how often does this happen in a real problem?'' reminds me of Intel's argument that the FDIV BUG didn't matter because it happened very rarely. IBM's analysis found that it happened many thousands of times per day, contrary to Intel's rarely. Remember, this error-prone sign test could be buried deep in a large program, called millions of times, and you have no idea what values are thrown at it.
For a nice history of the Pentium FDIV bug see here:
and for the sign test see here:
In a previous comment you say ``Nothing is wrong with the comparison of the SIGNs [ if sign(previous) == sign(current) ], see my first suggestion. It makes it only harder to handle the cases of zero values.''
How about if sign(1/previous) == sign(1/current) ?
Mathematically sign(x) = sign(1/x), x ~= 0, so this test handles all non-zero values along with signed zeros.
The difficulties in defining machine precision are discussed by Nick Higham and Cleve Moler here:
Jan
on 18 Dec 2012
@Derek: I do not think that this dicussion matchs the complexity level of the OP's question. If a user asks for different signs of two values, the topic "a*b<0" should be mentioned. I hope, that the OP feels encouraged to find such trivial solutions by his own in the future.
There is absolutely no doubt, that a multiplication can lead to numerical difficulties. Neither the famous FDIV story nor a discussion about common errors is required to prove this.
sign(1/x) will suffer from 1/realmin ~= realmax.
Sindar
on 29 Oct 2019
A method safe against overflow.
counting zeros as not a sign change
Sign changes:
if sign(prior_value)*sign(current_value) == -1
Sign stays the same:
if sign(prior_value)*sign(current_value) ~= -1
counting zeros as a sign change (even 0,0)
Sign changes:
if sign(prior_value)*sign(current_value) ~= 1
Sign stays the same:
if sign(prior_value)*sign(current_value) == 1
In all expressions, replace '*' with '.*' to allow prior_value and current_value to be vectors (or matrices), and return a vector of locations where the sign changes. If you want to check whether all the signs change, wrap with all(). Wrap with any() to check if any of the signs change.
Categories
Find more on Performance and Memory 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!