Can anyone help me to understand why the following:
set theList to {7.5, 11.7, 16, 13.7, 7.5, 3}
set TheTotalPrice to 0
repeat with x in theList
--display dialog x
set thePrice to x --as number
set TheTotalPrice to TheTotalPrice + thePrice
end repeat
display dialog TheTotalPrice
Results in this:
59.40000000000001 displayed in a dialog box
Yet I get 59.4 if I just return the result.
Help would be greatly appreciated, as this is small part of a much bigger project and is causing major hassles.
Looks like round-off error. The problem is that any decimal number has to be converted into binary for arithmetic. That conversion is seldom perfect and little dangling errors like this creep in.
This is true of any program in any computer. It looks like Apple Script wasn’t written with arithmetic in mind, since the r.o. error crept in with so few numbers.
Using a round off function, you should be able to keep your result accurate to 5 or 6 decimal places. If you need greater accuracy than that, an application designed for number crunching (e.g. a spreadsheet) would be a better tool for calculation.
Edit: I take that back, sort of. What I wrote about round off error is correct, but the following script returns 59.4, even though 59.0000000000001 is shown in the dialog box. (Returning TheTotalPrice as text returns “59.4”( Apparently the r.o. error is creeping in the display dialog line rather than in the calculations.
set theList to {7.5, 11.7, 16, 13.7, 7.5, 3}
set TheTotalPrice to 0
repeat with x in theList
--display dialog x
set thePrice to x as real
set TheTotalPrice to TheTotalPrice + thePrice
end repeat
display dialog TheTotalPrice
return TheTotalPrice
-- 59.4
Reals (numbers with fractional parts) are stored and handled in binary form, which means that they’re often just very close approximations of the decimal fractional numbers they’re supposed to represent. AppleScript does a pretty good job of converting between the two, but even it is defeated sometimes. (Try compiling the number 8484.38, for example.)
In your case, there are two things happening. Firstly, within the precision of AppleScript reals, the binary result of adding the numbers in your list isn’t precisely the same as the binary representation of 59.4:
Secondly, although the AppleScript language manages to compensate for the imprecision, the conversion in this case is being done by the ‘display dialog’ command in the StandardAdditions, which was designed principally for displaying text and only has a rudimentary ability with numbers. For AppleScript-language precision, get AppleScript to coerce the number to text and display that:
set theList to {7.5, 11.7, 16, 13.7, 7.5, 3}
set TheTotalPrice to 0
repeat with x in theList
--display dialog x
set thePrice to x --as number
set TheTotalPrice to TheTotalPrice + thePrice
end repeat
display dialog (TheTotalPrice as text)
Edit: Sorry. I didn’t notice mikerikson’s reply before posting this, but I think we’ve covered the ground between us.
Thanks for all the feedback guys. This has been an interesting lesson into programming, especially since I’m not a programmer, I’m a cafe owner!!!
To solve my issue of handing the correct value to another part of my script, I did pretty much what you guys suggested.
I set the result as a string (or text, I guess) then set it back to a number, thereby letting applescript look after the coercion for me!
It worked a treat for what I need.
set theList to {7.5, 11.7, 16.0, 13.7, 7.5, 3.0}
set TheTotalPrice to 0.0
repeat with x in theList
set thePrice to x
set TheTotalPrice to TheTotalPrice + x as string -- <-- making AS work for me!
end repeat
set TheTotalPrice to TheTotalPrice as number
display dialog TheTotalPrice