0

I have two buttons in Flash. The aim is that when you click one, the counter will go up by 1.9, and if you click the other it will go down by 1.9. However when you try and increase/decrease the number by 1.9, the math is slightly off after a few clicks. The number is one or two decimals from what it should be.

var count1:uint = 0;
var unit:Number = 0;

add1_btn.addEventListener(MouseEvent.CLICK, add1);
take1_btn.addEventListener(MouseEvent.CLICK, take1);
counter1.text = '0';

function add1(event:Event):void
{
count1++;
counter1.text = count1.toString();
unit+= 1.9; 
var unitRound= int((unit)*10)/10;
units.text = unitRound.toString();
}

function take1(event:Event):void
{
count1--;
counter1.text = count1.toString();
unit-= 1.9; 
var unitRound= int((unit)*10)/10;
units.text = unitRound.toString();
}

2 Answers2

1

What you are experiencing is the decimal imprecision of Flash's method of adding floating numbers.

To get around this, you can do the following. I simply changed how the addition is being done, and because of this, it allowed me to get rid of the unitRound variable that you were using while still keeping the single decimal precision you need.

var count1:uint = 0;
var unit:Number = 0;

add1_btn.addEventListener(MouseEvent.CLICK, add1);
take1_btn.addEventListener(MouseEvent.CLICK, take1);
counter1.text = '0';

function add1(event:Event):void
{
    count1++;
    counter1.text = count1.toString();
    unit = ((unit*10) + 19)/10;
    units.text = unit.toString();
}

function take1(event:Event):void
{
    count1--;
    counter1.text = count1.toString();
    unit = ((unit*10) - 19)/10;
    units.text = unit.toString();
}

Another slightly cleaner method I came across which does something similar to what I came up with, but easier to modify if needed:

var count1:uint = 0;
var unit:Number = 0;

add1_btn.addEventListener(MouseEvent.CLICK, add1);
take1_btn.addEventListener(MouseEvent.CLICK, take1);
counter1.text = '0';

function add1(event:Event):void
{
    count1++;
    counter1.text = count1.toString();
    unit = toFixed(unit + 1.9,10);
    units.text = unit.toString();
}

function take1(event:Event):void
{
    count1--;
    counter1.text = count1.toString();
    unit = toFixed(unit - 1.9,10);
    units.text = unit.toString();
}

var toFixed:Function = function(number:Number, factor:int) {
  return Math.round(number * factor)/factor;
}
Community
  • 1
  • 1
Anil
  • 2,539
  • 6
  • 33
  • 42
  • 1
    For the record, the floating point problem is not Flash/ActionScript specific. More on the subject at http://floating-point-gui.de/ – Lars Blåsjö Feb 19 '14 at 20:37
1

This is something you experience on any computer when working with decimal values.

Easiest workaround across all programming languages is probably to rework solution into something like this: (The key is to keep the thing you are iterating on clean of decimal points and then multiplying it with something to get the "final" value).

var _index:int = 0;

add1_btn.addEventListener(MouseEvent.CLICK, add1);
take1_btn.addEventListener(MouseEvent.CLICK, take1);
counter1.text = '0';

function add1(event:Event):void
{
_index++;
units.text = (_index * 1.9).toString();
}

function take1(event:Event):void
{
_index--;
units.text = (_index * 1.9).toString();
}
Daniel MesSer
  • 1,191
  • 1
  • 7
  • 13
  • +1 for the explanation and general advice, but I believe the example code, as it stand now, won't solve the problem and still produce output like "5.699999999999999". – Lars Blåsjö Feb 21 '14 at 09:47