Page 1 of 1

If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 3:03 pm
by Josh
Can anyone explain why the evaluation of If and Bool float values are rounded?

For me, zero is #False and everything else is #True

Code: Select all

Debug Bool (Not 0.4)
Debug Bool (Not 0.5)

If 1.0/2
  Debug "#True"
Else
  Debug "#False"
EndIf

If 1.0/3
  Debug "#True"
Else
  Debug "#False"
EndIf

Re: If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 5:01 pm
by skywalk
I am sort of confused?

Code: Select all

Define.d x,y
Define.i ix,iy
x = 1.0 / 2
y = 1.0 / 3
Debug "-- Doubles assigned a Double --"
If x
  Debug "F:1/2    = True"
Else
  Debug "F:1/2    = False"
EndIf
If Bool(x)
  Debug "BF:1/2   = True"
Else
  Debug "BF:1/2   = False"
EndIf
If y
  Debug "F:1/3    = True"
Else
  Debug "F:1/3    = False"
EndIf
If Bool(y)
  Debug "BF:1/3   = True"
Else
  Debug "BF:1/3   = False"
EndIf
Debug "-- Integers assigned a Double --"
ix = 1.0 / 2
iy = 1.0 / 3
If ix
  Debug "I:1.0/2  = True"
Else
  Debug "I:1.0/2  = False"
EndIf
If Bool(ix)
  Debug "BI:1.0/2 = True"
Else
  Debug "BI:1.0/2 = False"
EndIf
If iy
  Debug "I:1.0/3  = True"
Else
  Debug "I:1.0/3  = False"
EndIf
If Bool(iy)
  Debug "BI:1.0/3 = True"
Else
  Debug "BI:1.0/3 = False"
EndIf
Debug "-- Integers assigned an Integer --"
ix = 1 / 2
iy = 1 / 3
If ix
  Debug "I:1/2    = True"
Else
  Debug "I:1/2    = False"
EndIf
If Bool(ix)
  Debug "BI:1/2   = True"
Else
  Debug "BI:1/2   = False"
EndIf
If iy
  Debug "I:1/3    = True"
Else
  Debug "I:1/3    = False"
EndIf
If Bool(iy)
  Debug "BI:1/3   = True"
Else
  Debug "BI:1/3   = False"
EndIf
; -- Doubles assigned a Double --
; F:1/2    = True
; BF:1/2   = True
; F:1/3    = True
; BF:1/3   = True
; -- Integers assigned a Double --
; I:1.0/2  = True
; BI:1.0/2 = True
; I:1.0/3  = False
; BI:1.0/3 = False
; -- Integers assigned an Integer --
; I:1/2    = False
; BI:1/2   = False
; I:1/3    = False
; BI:1/3   = False

Re: If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 6:39 pm
by spikey
Josh wrote:For me, zero is #False and everything else is #True
No, strictly speaking, in Boolean algebra True is True and False is False, and neither is a number. But when programming, just like integers and floats these values get 'cast' into binary which can be stored in a register.
Josh wrote:Can anyone explain why the evaluation of If and Bool float values are rounded?
Think about each part of the statement individually as language not code - there's an underlying logic error.

Bool - make a true/false determination
Not - on the result of the true/false inversion
0.4 - of a continuous value.

In real world logic this makes no sense. Don't think of 0.4 as a discrete value - it isn't, its 0.40000000000000000000000......

However the compiler has a set of optimisation rules that it follows, and one of these is an implicit cast which says 'if you are put in a situation where a continuous variable is supplied as the operand of a function expecting discrete values - round it according to these rules'.
What the rule doesn't say is 'unless boolean functions are involved somewhere else'.

So the resulting program:
makes a true/false determination
on the result of the logical inversion
of a continuous value rounded according to the rules.

In C++ compilers you'd probably get an error or a warning about not using an explicit cast. This is one of those situations where the 'GIGO' rule applies.

Re: If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 8:20 pm
by spikey
skywalk wrote:I am sort of confused?
This one is more difficult to explain but the problem stems from a similar root cause - falling foul of casting.

To see how it comes about you have to look at the resulting assembler. In the first group the compiler elects for floating point instructions on floating point data values, unsurprisingly. However in the second and third groups it elects for integer instructions on integer data. However the integers selected for assignment differ from the second to third groups.

You'd need to look at the compiler's source code to be definitive but I'd guess this is because a different implicit cast rule in the compiler gets invoked in the second group compared with the third and there is a slight discrepency in the corresponding output.

Code: Select all

; Debug "-- Integers assigned a Double --"
; ix = 1.0 / 2
  MOV    qword [v_ix],1
; iy = 1.0 / 3
  MOV    qword [v_iy],0

; Debug "-- Integers assigned an Integer --"
; ix = 1 / 2
  MOV    qword [v_ix],0
; iy = 1 / 3
  MOV    qword [v_iy],0

Re: If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 8:53 pm
by skywalk
Thanks, I did not consider the ASM. This lessens the confusion, but I now have heartburn why the following are not all identical? The rule for a Constant assignment takes precedence over the datatype?

Code: Select all

Define.d x,y, divisor2, divisor3
Define.i ix,iy, idivisor2, idivisor3
divisor2 = 2
divisor3 = 3
idivisor2 = 2
idivisor3 = 3
Debug "-- Integers assigned a Double constant --"
ix = 1.0 / 2
iy = 1.0 / 3
If ix
  Debug "I:1.0/2  = True"
Else
  Debug "I:1.0/2  = False"
EndIf
If Bool(ix)
  Debug "BI:1.0/2 = True"
Else
  Debug "BI:1.0/2 = False"
EndIf
If iy
  Debug "I:1.0/3  = True"
Else
  Debug "I:1.0/3  = False"
EndIf
If Bool(iy)
  Debug "BI:1.0/3 = True"
Else
  Debug "BI:1.0/3 = False"
EndIf
Debug "-- Integers assigned a Double variable --"
ix = 1.0 / divisor2
iy = 1.0 / divisor3
If ix
  Debug "I:1.0/2  = True"
Else
  Debug "I:1.0/2  = False"
EndIf
If Bool(ix)
  Debug "BI:1.0/2 = True"
Else
  Debug "BI:1.0/2 = False"
EndIf
If iy
  Debug "I:1.0/3  = True"
Else
  Debug "I:1.0/3  = False"
EndIf
If Bool(iy)
  Debug "BI:1.0/3 = True"
Else
  Debug "BI:1.0/3 = False"
EndIf
Debug "-- Integers assigned a Double variable --"
ix = 1.0 / idivisor2
iy = 1.0 / idivisor3
If ix
  Debug "I:1.0/2  = True"
Else
  Debug "I:1.0/2  = False"
EndIf
If Bool(ix)
  Debug "BI:1.0/2 = True"
Else
  Debug "BI:1.0/2 = False"
EndIf
If iy
  Debug "I:1.0/3  = True"
Else
  Debug "I:1.0/3  = False"
EndIf
If Bool(iy)
  Debug "BI:1.0/3 = True"
Else
  Debug "BI:1.0/3 = False"
EndIf
; -- Integers assigned a Double constant --
; I:1.0/2  = True
; BI:1.0/2 = True
; I:1.0/3  = False
; BI:1.0/3 = False
; -- Integers assigned a Double variable --
; I:1.0/2  = False
; BI:1.0/2 = False
; I:1.0/3  = False
; BI:1.0/3 = False
; -- Integers assigned a Double variable --
; I:1.0/2  = False
; BI:1.0/2 = False
; I:1.0/3  = False
; BI:1.0/3 = False

Re: If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 9:33 pm
by Josh
I am a user of Pb and I am not interested in compiler-internas. If and Bool belong to the basic things of a programming language and there Pb should bring a result which is to be expected.

Other confusing examples:

Code: Select all

q.q = 2
d.d = 2.1

;Example with variables
Debug Bool (q = d) ; 1
Debug Bool (d = q) ; 0

;Same example with literals
Debug Bool (2 = 2.1) ; 0.0 (since when is a boolean value a float)
Debug Bool (2.1 = 2) ; 0.0

Re: If, Bool - rounded Floats

Posted: Tue Mar 20, 2018 9:41 pm
by skywalk
'0.0 +' saves the day :wink:

Code: Select all

; Example with variables
Debug Bool(0.0 + q = d) ; 1
Debug Bool(0.0 + d = q) ; 0
; Example with literals
Debug Bool(0.0 + 2 = 2.1) ; 0.0 (since when is a boolean value a float)
Debug Bool(0.0 + 2.1 = 2) ; 0.0