This board is for PLC Related Q&A ONLY. Please DON'T use it for advertising, etc. 

Try our online
PLC Simulator FREE.
Click here now to try it.

New Here? Please read this important info!!!
July 31st, 2009, 03:14 PM  #1 
Member
Join Date: Aug 2005
Location: Calgary
Posts: 92

RSLogix 5000  AOI  Rounding
I am trying to create an addon instruction to round a value.
I have defined the following parameters for the instruction INPUT: ValueToRound > REAL INPUT: Places > DINT OUTPUT: RoundedValue > REAL I've written the code as follows IntermediateValue1 = ValueToRound*(10^Places) DecimalPortion = IntermediateValue1  TRUNC(IntermediateValue1) If DecimalPortion >= 0.5 Then RoundedValue = TRUNC(IntermediateValue1+1)/(10^Places) Else RoundedValue = TRUNC(IntermediateValue1)/(10^Places) End_If My problem is as follows: If I enter ValueToRound = 3676.4444 Places = 2 The function calculates the values as 3699.9998 not 3700 as I expected. I assume it has something to do with the floating point math but can't figure out why. Dividing a truncated value by a power of 10 should work. Any Suggestions? 
July 31st, 2009, 04:22 PM  #2 
Lifetime Supporting Member

First off, I have to ask, why are you rounding? Except for display purposes, there is seldom an good reason to round IEEE754 floats, and the operations to do it are rather complex.
I apologize if this seems a bit pedantic, I'm just trying to explain what the challenges are in what you are trying to do. There are many numbers that cannot be exactly represented in the IEEE754 floating point format. 36.764444 happens to be one of those. So right out of the chute, you encounter a problem. This one however doesn't have a say in the outcome, as all you are doing is looking to see is if .764444 is greater than or less than .5. It is greater than so it seems intuitive that if you add one to 36, giving you 37, you are good do go. But in order to get there, you want to multiply and divide by 10^2, and here is where you hit a brick wall. 0.01 is another number that cannot be represented in an IEEE float. Instead, .01 becomes .0099999998. Look at the result you actually got and its pretty obvious where this is going. I have even more bad news. Not only is .01 not exactly representable, but .1, .001, .0001, .00001, .... .000000000000000000001, etc are all numbers that cannot be exactly expressed in IEEE754 float format. And those happen to be the very numbers expressed as 10^n. Now modern programs have complex algorithms that round values for display as a string of characters on your computer screen, so you see .01 on your screen, but that is a string, not a number. Inside, in memory it is .0099999998, and when you perform a computation that is what is used. So, what to do about it? What is the range of numbers that you will be using? Is the conceivable range of numbers, after shifting the decimal place, within the range of a DINT? I suspect that they are  besides, long before you exceed the range of a DINT your float will start to suffer from resolution problems that render rounding to two or three decimal places moot, but that is another topic altogether. So if the answer is yes, then I suggest you multiply or divide depending on the sign of n by 10^n where 10^n is a positive integer, not a float, and make the destination address a DINT. This will automatically round. Then divide or multiply by 10^n again depending on the sign of n to an integer destination, then move that to your float. In your example, start with CPT XTAG (10**ABS(Places)) XTAG is type DINT Use XIC Places.31 and XIO Places.32 to see if Places is negative or positive. because bit Places.31 is set, Places is negative, so divide. DIV 3676.4444 XTAG DINT_TAG will put 37 in DINT_TAG rounding automatically (well not actually automatically, the processor will jump through all kinds of complex gymnastics to make the conversion, but it will do it for you instead of you coding it.) Now MUL DINT_TAG XTAG DINT_TAG will put 3700 in DINT_TAG. Finally, MOV DINT_TAG REAL_TAG For cases where N is positive, do the opposite, multiply first, then divide. Over at MRPlc.com in the downloads section http://forums.mrplc.com/index.php?au...s&showfile=761 I have posted a program written for the PLC/5 and SLC500 platforms that does tuncation and rounding by direct manipulation of the IEEE754 float's mantissa. You can take a look at it and see what's involved behind the scenes, but even it won't work for all possible numbers. Is places always going to be negative? If so then there are some other easy solutions. Last of all, I have to ask again, why are you rounding? I'm just asking because we have seen other posts here where someone was attempting to round a number and it really wasn't necessary and boiled down to a misunderstanding of what the number meant and how it was really represented in the processor.
__________________
True craftsmanship is only one more power tool away. That's the beauty of processors, they don't have emotions they just run code  The PLC Kid. Last edited by TConnolly; July 31st, 2009 at 05:17 PM. 
August 5th, 2009, 08:40 AM  #3 
Member
Join Date: Aug 2005
Location: Calgary
Posts: 92

Alaric thanks for the info.
I am rounding because I am required to do so by specificiation. We produce API well casing and are bound by the specification created by API. They define the hydrostatic test pressure using a calculation based on pipe diameter, wall thickness, and specified minimum yield strength. The result of the calculation is then to be rounded to the nearest 100 psi and used as the test pressure for that particular product. I decided that while I was creating a rounding routine I had might as well create and AOI that I could reuse rather than just onetime code for this project. I took your advice and used DINT data types instead. Thanks for the help. I have never fully understood floating point data before. I always thought of it simply as a structure to hold a real number. Thanks Again. 
August 5th, 2009, 09:12 AM  #4  
Lifetime Supporting Member

I'm glad I was able to help.
Here is more info on how floats are stored:http://en.wikipedia.org/wiki/IEEE_7541985 If you want to see what a particular float looks like in Binary, here is a useful tool: http://babbage.cs.qc.edu/IEEE754/Decimal.html I need to make a correction to my post above. I wrote Quote:
Use XIC Places.31 and XIO Places.31 to see if Places is negative or positive. For those who may read this in the future but who don't understand what its doing, bit 31 of any dint is the sign bit. If it is set the number is negative, if it is clear the number is positive.
__________________
True craftsmanship is only one more power tool away. That's the beauty of processors, they don't have emotions they just run code  The PLC Kid. 

Bookmarks 
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)  
Thread Tools  
Display Modes  


Similar Topics  
Thread  Thread Starter  Forum  Replies  Last Post 
AOI in rslogix 5000  finibx  LIVE PLC Questions And Answers  3  July 6th, 2009 01:27 AM 
Day of week AOI error in RSLogix 5000  rta53  LIVE PLC Questions And Answers  0  January 9th, 2009 03:17 PM 
RSLogix 5000 Add On Instruction (AOI) to HMI  NFischer1978  LIVE PLC Questions And Answers  0  September 19th, 2008 06:13 PM 
Gray Code and RSLogix 5000  IAA  LIVE PLC Questions And Answers  5  September 28th, 2007 09:27 AM 
RSLogix 5000 V15 Features  Samneggs  LIVE PLC Questions And Answers  18  April 20th, 2006 05:45 PM 