How to handle floating point arithmetic errors in FlxObject.health?



  • I notice that FlxObject uses a Float to store its' health value. The codebook entry on using numbers says that floating point arithmetic is not always accurate. (https://code.haxe.org/category/beginner/numbers-floats-ints.html) I couldn't find a clear listing of what kind of errors can occur, but the example they give is where two floating point values are added, and the result is more than the sum. So as I understand it, you could end up with a situation where health should be 0, but the object doesn't call kill() because the actual value of health is slightly more than 0 due to floating point arithmetic errors. How do I avoid this? Do I have to round health every time I change its' value?

    Thanks.



  • EDIT: misunderstood the topic.
    hi @chartype. you would need to convert a Float to an Int. https://api.haxeflixel.com/Std.html



  • @galoyo How would that help? FlxObject.health is a Float. I could convert it to an int and then back to a float, but that would just be the same as rounding it.



  • EDIT: misunderstood the topic.
    you just convert a variable. just do if (std.int(health) <= 0).



  • @CharType

    Std.int() floors it, so might not be best since 0.99 will end up 0. Math.round() is better, but still 0.49 will end up 0.

    Std.int(0.99) = 0.
    Math.floor(0.99) = 0
    Math.ceil(0.01) = 1
    Math.round(0.5) = 1
    Math.round(0.49) = 0

    you can do this to remove the rounding error crumbs:
    health = Math.round(health * 10) / 10;
    try it here: https://try.haxe.org/#6DDE4



  • or maybe this

    override public function hurt(damage:Float):Void 
    {
    	super.hurt(damage);
    	
    	if (health > 0 && health < 0.01) // close enough to 0
    	{
    		kill();
    	}
    }
    


  • Thanks everyone for the responses. One thing I was wondering was whether this kind of error can happen at all, since all the examples I've seen use health as though it's an exact value and they seem to work fine. I don't know anything about how Haxe handles floats internally, so for all I know it's entirely possible that the regular float checking in the hurt() function works as expected, and the codebook is just wrong or at least misleading.

    Probably best to play it safe. So anyway, these are all good suggestions. I'll probably do what dean suggested and override hurt().


Log in to reply
 

Looks like your connection to HaxeFlixel was lost, please wait while we try to reconnect.