LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Change/add math vi's to prevent rounding errors

Although the Labview math VI's follow the IEEE standards, this makes for some completely useless VI's.
 
For example, the "Quotient and Remainder"  VI gives unexpected (dare I say wrong) results when used with floating points. For example,  1.2 divide by 0.2 gives 5 with a remainder of 0.2....  According to IEEE standards for floating point operations, this is computational correct behaviour... but obviously not what normal (human) mathematics gives you.   And that makes this vi's pretty useless.
 
The problem is ofcourse caused by the quantization error made in representing floating points in a DBL computer represenation, and the rounding errors when doing math on them.  Normally, this doesn't influence the results, because the final result is rounded to a smaller number of significant digits than the internal representation, which removes any quantization and rounding error effects.
 
However, in some situations, it's not sufficient to round at the end of the track...   The Quotient and Remainder VI is one example of such a situation.   Here, one must first remove rounding errors, before continuing the computation, to produce mathematically correct results.
 
The actual problem for the quotient and remainder VI lies in the floor operation.  Rounding errors in the last few digits can decide to which integer the value is rounded, and thus have a enormous effect on the end result. And that's happening in the Quotient and Remainder VI.   The solution is actually quite simple...   First remove the rounding errors, (by reducing the value to a smaller number of significant digits) and then perform the floor operation. 
 
A conversion from DBL to SGL just before the floor does the job perfectly, and is very fast.  If you want a larger number of significant numbers, you'll need a proper 'round to # significant digits' routine.  (See example vi's)
 
 
These rounding problems only occur in floating point comparison and rounding routines.  People generally know that you should never test for equality between floating points...   But why include such an operator if you should never use it?
 
In stead of having a set of IEEE compliant, but quite useless VI's, I would suggest to change the default behaviour of (some of) these specific VI so that they give mathematically meaningfull results.   The best approach would probably be to include a 'mode option'  where one can choose between 'IEEE compliant'  and 'Rounded'    
 
Ofcourse, these VI's would have an optional input for determining the number of significant digits yourself, but I think that a default of 10 significant digits would suite almost every situation where you would use these types of VI's.   (How often do you do a Quotient and Remainder on x= 1.2000000000 and y=0.2000000001 ? )

 

NB: The goal is not so much to replace the IEEE math... but to prevent that we need to write all workarounds for every day calculation.   I'm sure that NI could make a faster 'round to # significant digits'  than my version...     We have tons of higher level VI's for all kinds of complicated operations... it seems silly that we don't have VI's to handle these basic problems.

Message Edited by Anthony de Vries on 10-12-2007 03:55 PM

Message 1 of 45
(4,736 Views)
This has the possibility of becoming another 9-page thread that you actually started on the Q&R function. To be honest, I don't even know what the conclusion from that thread was, but it seems to me that there's nothing wrong with having two versions of a few of the functions and have the secondary version use the rounding mechanism that you propose. I would not agree with changing the behavior of the existing primitives (they're not VIs, by the way), as that would mean LabVIEW would not work like just about every other programming language. That's not to say that just because everybody does it a certain way it's right, but at least the behavior is known.

I don't quite get your point about the inclusion of the equality operator because "it doesn't work with floats". Are you suggesting that wiring a floating point to this operator should be disallowed?
0 Kudos
Message 2 of 45
(4,700 Views)
If you don't like how the quotient & remainder behaves with dbls, don't wire
dbls to it! It is polymorphic, so simply convert the dbl to an integer.

Can't view your vi's right now, can you post a png?

Regards,

Wiebe.



0 Kudos
Message 3 of 45
(4,688 Views)

Let me assure you, I don't intend to create another Mega thread!  Smiley Very Happy 

But I would like to get extended or additional math operators in Labview.   I now have my own replacement VI's that do the job, but it seems silly that those aren't built into Labview.   I have used my own floating point QR quite a lot actually.

As for the floating point equality....   That thing gives totally unpredictable results with most fractional numbers.  Then you can certainly question why you allow users to do so?     You might just as well wire to a random vi...    

Ofcourse, when the user is going to make his own equality operator that takes care of the rounding errors, he might need a float equality primitive. But then, it makes more sense to allready include such a extended equality primitive in Labview in the first place... 

I find it odd that we did get fixed-point variables and operators, but not this little extra bit of functionality in the floating points operators.

0 Kudos
Message 4 of 45
(4,688 Views)

Well Wiebe...   Try putting 0.2 into an integer.  Smiley Tongue

As far as I am concerned...   when QR accepts floating points, then it also should give meaningfull answers.  Makes no sense to make a polymorphic floating-point version, that gives unexpected results. 

Here's the vi's in PNG:  

Round to # significant numbers:

Comparison of different QR routines
.  

I used the SGL version mostly, as that was sufficient for my purposes.  But for a more general routine, I think the rounding to # significant numbers is better.   

If you'd change the default behaviour of the floor routine, then the Labview QR routine would probably be fixed automatically...  But that's something for NI to decide.   

I wouldn't be surprised if the "In Range and Coerce" operation suffers from the same issue.

Message Edited by Anthony de Vries on 10-12-2007 06:04 PM

Download All
0 Kudos
Message 5 of 45
(4,681 Views)
Personally, I would prefer if the Quotient/Remainder issue isn't rehashed in this thread. As pointed out, you've already had a lengthy discussion on this, and the debate as to whether this is a bug or not is just that: debatable. Obviously this is your thread, but I think that the original point of your message should be the focus here: whether there is a benefit in providing alternate versions of some of these primitives. I think that would be a more fruitful discussion than debating the Quotient/Remainder business yet again.
0 Kudos
Message 6 of 45
(4,666 Views)
Back in the day, NI only supplied a basic set of math functions.  There was not even x^y function.  My point being here, if the functions suit 80%+ of the users, there is nothing for NI to gain by 'fixing' it, when you obviously have ALREADY done that.  My solution to the DBL problem when it does occasionally creep up, is to multiple it up by the required number of sig digits, change it to an integer, perform my function, then divide back down.  As you indicated, they are doing it right by IEEE standards, then if you want to make a point, what standard can you point to, that does it the way you are describing?  And more to the point, it seems that it will not really help you anyway, as you have effected a solution.  It seems that this is your white whale captain Ahab.  If you have made your product suggestion to NI, and have voiced this in a thread already once,
What do you hope to gain by bringing it up again?  I can tell you NOW, NI will not assure you a change (unless it is already in a build that is committed to release) which I can assure you that it is not right now today.

Paul
0 Kudos
Message 7 of 45
(4,650 Views)

The equality operator is already bi-modal in some contexts.  When fed two clusters, one can right-click to decide whether to do an aggregate comparison with a boolean output or an element comparison with a cluster-of-booleans output.  So there *is* some precedent for handling equality comparisons in special ways... 

Still, I think that if I were NI, I wouldn't want to touch this one before some considerable degree of consensus emerged on expected behaviors and implementation.  There are quite a few comparison operators.  Even a pure "greater than", which hasn't been discussed yet, might need to be considered.  To wit, suppose you compare values that vary only by something like 1e-15.  In some contexts, you might want to consider these equal and thus have a "greater than" comparison" return False.

So I think that due to the number of comparison functions, their implementation is more problematic.  Do you make a whole new palette of comparison functions solely to handle floating-point inputs and allow rounding?  Do you add an optional input to all the existing primitives to specify behavior with floating point inputs?  Do you make them polymorphic with a visible menu to select the desired instance, like many of the DAQmx data acq functions?   I would tend to include both "Search 1D Array" and "Threshold 1D Array" in this group as essentially comparison-based functions.  "In Range & Coerce" has already been mentioned.  There are probably others too.

Apart from the comparison functions, "Q-R" was also mentioned as a numeric function to consider for alternate behavior.   What others should be considered?  I think the numeric "Sign" function is a potential candidate but of somewhat lesser priority than Q-R.   What others?  (Personally, I considered mentioning primitives like "Sqrt", "1/x", and "Divide", but decided that they were too much of a stretch).

I agree with smercurio's replies.  Existing operators & functions need to retain current behavior by default, but there may be value in providing optional alternatives for some of them.  "Q-R" is surely one case and Anthony has provided some implementations to consider.  I can certainly think of scenarios where I'd prefer to drop a function like his on my diagram than to use the native Q-R.  I've been using an analogous home-grown "approximately equal" vi for years because it sometimes suits my needs better than official IEEE floating-point equality.  In the end, *usefulness* is reason enough for a specialty vi. 

Overall, this seems like the kind of thing that might gain traction as a set of OpenG tools.   Oh, look!  There's already a similar discussion going on...  

-Kevin P.

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 8 of 45
(4,644 Views)

You're right Kevin, this would also affect the greater than function. Basicly, it affects all comparison operators, and operations that rely on it. 

But I think that in the end, the total number of actual changes would small...  I don't know how exactly things like floor are implemented, but I wouldn't be surprised that when you have an alternative equal, greater than and smaller than, that all other comparison operations automatically follow. Certainly, to make the alternate QR, you only need to use the alternate floor. The function itself doesn't change.  Same for the sign function.

Just to be clear... this doesn't affect things like 1/x, sqrt or divide.  You absolutely shouldn't do any rounding there. 

 

Interesting to read the OpenG discussion. 

0 Kudos
Message 9 of 45
(4,623 Views)
Re: 1/x, sqrt, divide.   Yeah you're right.  Leave those alone.  I was thinking of the degenerate cases where the input values *should* be 0 but due to floating-point roundoff might actually range from -1e-15 to +1e-15.  Then the outputs become extraordinarily sensitive to the tiniest change in input.
 
However, rather than a special version of each of those 3 functions (plus any others that become degenerate for values that are almost but not quite = 0), a better approach would be a single convert function that would, say, round off the least significant N bits of the mantissa.   (Very analogous to your "signif digits" rounding, but potentially a much faster calc via bit operations.  On the other hand, harder to relate to than base10 signif digits.)  The effect would be to convert any such tiny epsilon values to a true IEEE 0, including any tweaking of the sign bit (if needed).  Then the programmer could decide whether or not to do that conversion prior to calling those sensitive functions.  Such a conversion function would also cover the troubles with the "Sign" function.  (Don't think floor() would work properly because a negative epsilon would get floor'ed down to -1 instead of converting to 0).
 
So, two items for the toolkit would be a tweaked Q-R intended to compensate for floating-point roundoff, and a conversion function that helps round off some of the uncertain bits in a floating point number.
 
I'll need to play around a bit, but if I recall correctly, I further found the standard Q-R treatment of negative input(s) to be a bit counter-intuitive.  Again, very likely technically correct, just not what I expected.  It probably relates to the way floor() rounds toward -Infinity, where I was expecting something like abs_floor() that would round toward 0, i.e., lower absolute value.
 
For example, suppose you're dealing with a value representing db gain and you want to express it as an integer part plus a fractional part.  I don't know why, you just do.  So if you've got 27 db, you would use Q-R to divide by 10 and get +2 + 7/10 order of magnitude.   On the other hand, if you had -27 db, you'd use Q-R to divide by 10 and get -3 + 3/10 order of magnitude.  Weird to me.  I'd rather get a result like  -2 - 7/10, so that both the integer part and the fractional part have the same sign.
 
For anyone interested in hashing out a Q-R consensus, what do y'all think about handling negative input(s)?
 
-Kevin P.
ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 10 of 45
(4,610 Views)