• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

[Solved] Weird R2I() behaviour

Status
Not open for further replies.
Could someone explain this to me?
JASS:
   set udg_PatrolSystemState = 1.1
   call BJDebugMsg(R2S(udg_PatrolSystemState)) // 1.100
   set udg_PatrolSystemState = udg_PatrolSystemState-0.1
   call BJDebugMsg(R2S(udg_PatrolSystemState*10)) // 10.000
   call BJDebugMsg(I2S(R2I(udg_PatrolSystemState*10))) // 9 <== WTF?

It's been a real headache even figuring out this is what's going wrong, it makes absolutely no sense to me.

Edit: I just tested in a separate trigger and it's not happening there. No idea what's going on.
Edit2: updated the code above. The subtraction of 0.1 is somehow being repeated by putting the variable through R2I o_O

Edit3: I guess real subtraction is just horribly imprecise in JASS... probably instead of -0.1 it does -0.1000001 or something.
Either that or the R2I function isn't very good.

JASS:
    set udg_PatrolSystemState = 1.1
    call BJDebugMsg(R2S(udg_PatrolSystemState*10)) // 11.000
 
    set udg_PatrolSystemState = udg_PatrolSystemState-0.3
    call BJDebugMsg(R2S(udg_PatrolSystemState*10)) // 8.000
    call BJDebugMsg(I2S(R2I(udg_PatrolSystemState*10))) // 7 <== WTF?
 
    set udg_PatrolSystemState = 0.8
    call BJDebugMsg(I2S(R2I(udg_PatrolSystemState*10))) // 8
 
Last edited:

~El

~El

Level 17
Joined
Jun 13, 2016
Messages
558
This is most likely an artifact of floating point precision loss. In very simple terms: 1.1 - 0.1 does not equal 1.0, when you are using floating point arithmetic.

This is purely a guess, but R2S may be rounding the output from something like 7.99999... to 8.000, while R2I is rounding down to 7, effectively just cutting off the fractional part.

Or it could be a bug with R2I. JASS is notoriously bad with integer-real-string conversions (and there are a plethora of other subtle and weird bugs related to those).

EDIT: Case in point, using this handy converter, IEEE-754 Floating Point Converter , if you try to enter 0.1, it tells you that the actual value being stored is 0.100000001490116119384765625. If you try to substract this from from 1.1, you're going to get a value that is less than 1.0.
 
I suspected something like that. Still, you'd expect the R2I function to take this into account and correct for it.

I'm using reals because it's the only type of variable that has an event for a changing value. I was using R2I/I2R to delete the second decimal and replace it with another, but instead I'm now just setting the first digit and the first decimal again based on booleans I already have. It's not a big deal, except for 7 extra lines and a big waste of time figuring out what was happening.

Thanks for the feedback, and for the link, interesting read =)
 
Last edited:
FWIW, this is the approach I'm using now:
JASS:
       // These constants are passed to the function
        private constant real ALERT_NONE     = 0
        private constant real ALERT_RUNNER   = 0.01
        private constant real ALERT_ALERTED  = 0.02
        private constant real ALERT_ATTACKED = 0.03

    private function SetAlertState takes real alertState returns nothing
        local real state = 0
        if scriptOn then
            set state = 1
        endif
        if attackMode then
            set state = state+0.1
        endif
        set udg_PatrolSystemState = state+alertState
    endfunction

Whereas before it was like this:
JASS:
       // These constants are passed to the function
        private constant integer ALERT_NONE     = 0
        private constant integer ALERT_RUNNER   = 1
        private constant integer ALERT_ALERTED  = 2
        private constant integer ALERT_ATTACKED = 3

    private function SetAlertState takes real alertState returns nothing
        set udg_PatrolSystemState = I2R(R2I(udg_PatrolSystemState*10)) + I2R(alertState)/100
    endfunction

The scriptOn/attackMode parts of udg_PatrolSystemState are set elsewhere.
 
Last edited:
Status
Not open for further replies.
Top