From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Expecting a result of zero when subtracting, but getting 138.778E-18

Solved!
Go to solution

You are still using floating point value, so whatever you are doing is still troublesome.

 

Overall, you have way too many local variables and way too much duplicate code. For the BanksX and BX indicators, you could use arrays, shrinking the code to <10% of what it currently is. There is also a primitive for ">0".

 

You still have serious race conditions: There is no guarantee that the indicators on top receive the current values before their local variables are being read. You are potentially writing to BankTTL in seven different places in parallel. Seems poorly designed.

 

For the indicators, use an "f" format instead of automatic formatting, and you'll see zero if the value is close enough.

Message 11 of 18
(528 Views)

Thank you altenback. I will try implementing the code with what you suggest to clean it up. As far as seeing zero goes in the indicator, this would not fix the actual problem I was having.  What was happening with my code is that continually decrementing my value of '1' by 0.1 actually returned a result of '138.778E-18' after the tenth iteration instead of zero. As explained by Dennis and JKSH this is due to rounding errors with floating point numbers represented in a base 2 numbering system. Makes sense to me. So when I expected my logic to continue from one bank to the next after the tenth iteration, it would not because '138.778E-18' is still greater than zero.  The logic in my code would not reach the next bank until I subtracted .1 in the 11th iteration which is not what I wanted. So to correct this I just multiplied all my values by the maximum precision I wanted which was 1E+6 for six decimal places which worked well in the binary system (i.e. not having to worry about rounding errors for the precision I wanted).  Not sure if I was able to explain this clear enough or not, however it can be seen by the difference in running the two snippets of code that I provided.

0 Kudos
Message 12 of 18
(504 Views)

@MiBelli wrote:

Thank you altenback. I will try implementing the code with what you suggest to clean it up. As far as seeing zero goes in the indicator, this would not fix the actual problem I was having.  What was happening with my code is that continually decrementing my value of '1' by 0.1 actually returned a result of '138.778E-18' after the tenth iteration instead of zero. As explained by Dennis and JKSH this is due to rounding errors with floating point numbers represented in a base 2 numbering system. Makes sense to me. So when I expected my logic to continue from one bank to the next after the tenth iteration, it would not because '138.778E-18' is still greater than zero.  The logic in my code would not reach the next bank until I subtracted .1 in the 11th iteration which is not what I wanted. So to correct this I just multiplied all my values by the maximum precision I wanted which was 1E+6 for six decimal places which worked well in the binary system (i.e. not having to worry about rounding errors for the precision I wanted).  Not sure if I was able to explain this clear enough or not, however it can be seen by the difference in running the two snippets of code that I provided.


138.778E-18 times 1E+6 is still not zero, and will never be. 😉

0 Kudos
Message 13 of 18
(493 Views)

Of course not,  who ever said it did.  I never multiplied 138.778E-18 by 1e+6.  The value 138.778E-18 was a resultant value when executing the code.

0 Kudos
Message 14 of 18
(487 Views)

To clarify further,  the values that I multiplied by 1E+6 are all of the contstants and the inputs to the code.  as can be seen when you look at the two different VIs that I submitted.

0 Kudos
Message 15 of 18
(483 Views)

Hi altenback,

 

Thank you for your suggestions in how to clean up my code.  There may be a more elegant way, but I am satisfied.  In my attachment, I provide a VI that compares code that gives me the floating point rounding errors that I was experiencing and code that works as I expected.  I provide some comments in the code to explain the problem I was having.

 

The comparison VI includes the two SampleCode VIs.

 

 

 

0 Kudos
Message 16 of 18
(459 Views)

Generally, it is a bad idea to iteratively adjust a floating point value. With every iteration, your error grows bigger.

 

Here are 2 ways to decrement 100 by 0.1 until it reaches 0:

 

Float Error Accumulation.png

 

  • (This is what your code does) The top loop takes a value, subtracts 0.1 from it, and then stores the result in a shift register. In the next iteration, the value in the shift register is retrieved, another 0.1 is subtracted from it, and the result is stored back in the shift register for the next iteration to use.
  • The bottom loop doesn't use results from previous iterations -- it takes the original starting value and computes a new value to subtract.

If you probe this output, the last value of Results 1 is 1.404E-12 (10000 times greater than what you got!), while the last value of Results 2 is 0.000E+0.

 

When you multiply all your inputs by 10E6 and divide the final result by 1E6, you managed to shrink the errors a bit, but they are still there and they're still growing. If your number of iterations increase, your error could become significant again.

 

P.S. Do you understand what Altenbach meant when he said that your code has race conditions?

Certified LabVIEW Developer
Message 17 of 18
(443 Views)

Thank you JKSH,

 

Your last explanation was fantastic.  Yes, I do understand about race conditions. I was concerned about that with my original code, but did not have any ideas initially on how to eliminate the race conditions.

 

0 Kudos
Message 18 of 18
(433 Views)