LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
-
shawn
- Posts: 18
- Joined: Sat Jan 02, 2010 4:11 am
Post
by shawn » Sat Jan 01, 2011 6:10 pm
Anyone else seen problems with DIV when used with decimals? I am using it to break an amount of money into change. It seems to mishandle the pennies on occasion.
Try the following code....
Code: Select all
put "1.30" into change
put change div 20 into temp
if temp > 0 then
put temp && " Twenty Dollar Bill(s)" && return after list_change
put change - (temp * 20) into change
end if
put change div 10 into temp
if temp > 0 then
put temp && " Ten Dollar Bill(s)" && return after list_change
put change - (temp * 10) into change
end if
put change div 5 into temp
if temp > 0 then
put temp && " Five Dollar Bill(s)" && return after list_change
put change - (temp * 5) into change
end if
put change div 1 into temp
if temp > 0 then
put temp && " One Dollar Bill(s)" && return after list_change
put change - (temp * 1) into change
end if
put change div .25 into temp
if temp > 0 then
put temp && " Quarter(s)" && return after list_change
put change - (temp * .25) into change
end if
put change div .10 into temp
if temp > 0 then
put temp && " Dime(s)" && return after list_change
put change - (temp * .10) into change
end if
put change div .05 into temp
if temp > 0 then
put temp && " Nickels" && return after list_change
put change - (temp * .05) into change
end if
answer change -- to verify what we have here
put change div .01 into temp
answer temp -- to verify DIV result
if temp > 0 then
put temp && " Pennies" && return after list_change
put change - (temp * .01) into change
end if
When it hits the "answer change" you will get 0.05 and it will also calculate 5 pennies. If you change the first line from "put 1.30 into change" to "put 2.30 into change" when you get to the "answer change" you will still get 0.05... however the DIV will now come back and say .01 goes into .05 only 4 times which obviously isn't correct.
This is on livecode build 1150 version 4.5.2.
Any ideas?
Shawn
FIxed a bug that was keeping it from calculating nickels properly. Still seeing the same issue though at 1.30 it calculates 1 nickel at 2.30 it calculates 4 pennies.
-
bn
- VIP Livecode Opensource Backer

- Posts: 4166
- Joined: Sun Jan 07, 2007 9:12 pm
Post
by bn » Sat Jan 01, 2011 6:51 pm
Hi Shawn,
I see the same behavior as you do.
from the dictionary for DIV
Note: While using non-integer number and divisor usually produces sensible results, mathematically, integer division is generally defined as a function over the integers, and the results using non-integers may not consistently be what you expect.
I think you run into this problem.
Kind regards
Bernd
-
bn
- VIP Livecode Opensource Backer

- Posts: 4166
- Joined: Sun Jan 07, 2007 9:12 pm
Post
by bn » Sat Jan 01, 2011 7:01 pm
Hi Shawn,
Code: Select all
on mouseUp
put "2.30" into change
put round(change * 100) into change
put change div 2000 into temp
if temp > 0 then
put temp && " Twenty Dollar Bill(s)" && return after list_change
put change - (temp * 2000) into change
end if
put change div 1000 into temp
if temp > 0 then
put temp && " Ten Dollar Bill(s)" && return after list_change
put change - (temp * 1000) into change
end if
put change div 500 into temp
if temp > 0 then
put temp && " Five Dollar Bill(s)" && return after list_change
put change - (temp * 500) into change
end if
put change div 100 into temp
if temp > 0 then
put temp && " One Dollar Bill(s)" && return after list_change
put change - (temp * 100) into change
end if
put change div 25 into temp
if temp > 0 then
put temp && " Quarter(s)" && return after list_change
put change - (temp * 25) into change
end if
put change div 10 into temp
if temp > 0 then
put temp && " Dime(s)" && return after list_change
put change - (temp * 10) into change
end if
put change div 5 into temp
if temp > 0 then
put temp && " Nickels" && return after list_change
put change - (temp * 5) into change
end if
answer change -- to verify what we have here
put change div 1 into temp
answer temp -- to verify DIV result
if temp > 0 then
put temp && " Pennies" && return after list_change
put change - (temp * 1) into change
end if
put list_change into field 1
end mouseUp
this works for 2.30
Kind regards
Bernd
-
shawn
- Posts: 18
- Joined: Sat Jan 02, 2010 4:11 am
Post
by shawn » Sat Jan 01, 2011 7:14 pm
Bernd,
Even if I convert everything to cents (so all integer math) DIV still works inconsistently. Works properly starting with:
put "1.30" into change
change that to
put "2.30" into change
and it doesn't work again.
Code: Select all
put "1.30" into change
put change * 100 into change -- convert to pennies to make all math integer math
put change div 2000 into temp
if temp > 0 then
put temp && " Twenty Dollar Bill(s)" && return after list_change
put change - (temp * 2000) into change
end if
put change div 1000 into temp
if temp > 0 then
put temp && " Ten Dollar Bill(s)" && return after list_change
put change - (temp * 1000) into change
end if
put change div 500 into temp
if temp > 0 then
put temp && " Five Dollar Bill(s)" && return after list_change
put change - (temp * 500) into change
end if
put change div 100 into temp
if temp > 0 then
put temp && " One Dollar Bill(s)" && return after list_change
put change - (temp * 100) into change
end if
put change div 25 into temp
if temp > 0 then
put temp && " Quarter(s)" && return after list_change
put change - (temp * 25) into change
end if
put change div 10 into temp
if temp > 0 then
put temp && " Dime(s)" && return after list_change
put change - (temp * 10) into change
end if
put change div 5 into temp
if temp > 0 then
put temp && " Nickel(s)" && return after list_change
put change - (temp * 5) into change
end if
put change div 1 into temp
if temp > 0 then
put temp && " Penny(s)" && return after list_change
put change - (temp * 1) into change
end if
put list_change into field "list_change"
.
-
shawn
- Posts: 18
- Joined: Sat Jan 02, 2010 4:11 am
Post
by shawn » Sat Jan 01, 2011 7:28 pm
Added the round function like in your example and it seems to work now. It is kind of odd that the math engine isn't coming up with a whole number for 2.30 * 100.
Thanks,
Shawn
-
bn
- VIP Livecode Opensource Backer

- Posts: 4166
- Joined: Sun Jan 07, 2007 9:12 pm
Post
by bn » Sat Jan 01, 2011 7:31 pm
Hi Shawn,
note
Code: Select all
put round(change * 100) into change
in the code I posted. Then it works.
Integer math is difficult for computers because internally they do it all with floating point operations. But others know more about it.
Kind regards
Bernd
-
shawn
- Posts: 18
- Joined: Sat Jan 02, 2010 4:11 am
Post
by shawn » Sat Jan 01, 2011 8:03 pm
Bernd,
Sure, but if you have LiveCode multiple 2.30 * 100 and give you the answer it gives you an integer.
It is confusing and inconsistent that what it tells you the answer is isn't really what it is using for the answer in later calculations.
Thanks again for the help,
Shawn
-
bn
- VIP Livecode Opensource Backer

- Posts: 4166
- Joined: Sun Jan 07, 2007 9:12 pm
Post
by bn » Sat Jan 01, 2011 8:51 pm
Hi Shawn,
Code: Select all
on mouseUp
set the numberformat to ".##########################"
put 2.3 * 100 into field 1
end mouseUp
try this
Kind regards
Bernd
-
jsburnett
- VIP Livecode Opensource Backer

- Posts: 121
- Joined: Fri Mar 09, 2007 9:47 pm
Post
by jsburnett » Wed Jan 26, 2011 11:48 pm
Very interesting behavior.
I did notice that if you change the pennies to:
put (change/0.01) into temp
if temp > 0 then
put temp && " Pennies" && return after list_change
put change - (temp * .01) into change
end if
answer list_Change
It works all the time. At least with my testing.
(or not?).
JSB
-
BvG
- VIP Livecode Opensource Backer

- Posts: 1239
- Joined: Sat Apr 08, 2006 1:10 pm
-
Contact:
Post
by BvG » Thu Jan 27, 2011 1:53 pm
This is silly. the amounts are tiny, the numbers are integer and the calculation is explicitely trashing all non-integer results. I filed a bug:
http://quality.runrev.com/qacenter/show_bug.cgi?id=9346
as a workaround, always use the round function on each calculation for the followup amount. see my own test code:
Code: Select all
on mouseUp
put field "money" * 100 into theChange
put theChange into theOriginal
put "2000,1000,500,100,50,25,10,5,2,1" into MoneyList
put "20 bucks,ten bucks,five bucks,one buck,half a buck,quarter buck,ten dimes,five dimes,two dimes,one dime" into moneyNames
put 0 into theItem
repeat for each item theItem in moneyList
add one to theItemOffset
put theChange div theItem into temp
if temp > 0 then
put temp && "piece/s of" && item theItemOffset of moneyNames & return after theResult
put round(theChange - temp * theItem) into theChange
end if
end repeat
put 0 into resultSum
repeat for each line theLine in theResult
if the number of words of theLine > 0 then
put item itemoffset(word 4 to -1 of theLine,moneyNames) of moneyList into theMultiplier
add word 1 of theLine * theMultiplier to resultSum
end if
end repeat
put theOriginal && "original amount" & return & resultSum && "calculated amount" & return & return before theResult
put theResult into field list_change
end mouseUp
Various teststacks and stuff:
http://bjoernke.com
Chat with other RunRev developers:
chat.freenode.net:6666 #livecode
-
FourthWorld
- VIP Livecode Opensource Backer

- Posts: 10044
- Joined: Sat Apr 08, 2006 7:05 am
-
Contact:
Post
by FourthWorld » Thu Jan 27, 2011 3:08 pm
Thank you for that.
Computer science types are quick to apologize for the limits of a machine too stupid to count past 1, but programming languages serve the goals of humans, not the other way around. Simple arithmetic like this should be corrected for; if it can be done in script, it can be done in the engine.
-
mwieder
- VIP Livecode Opensource Backer

- Posts: 3581
- Joined: Mon Jan 22, 2007 7:36 am
-
Contact:
Post
by mwieder » Thu Jan 27, 2011 6:03 pm
Well, unfortunately it's not something that can be "fixed". There are ways to deal with this by rounding, but you have to be careful where you round or you can lose precision in the calculations and come up with the wrong results. It's not a LC problem as such - you're reaching the limits of computer calculation. It's a matter of trying to simulate an analog world in a digital computer - quantizing errors can build up.
Here's some background info
http://en.wikipedia.org/wiki/Machine_epsilon