SOLVED - Why doesn't this work (round a float via a procedure) ???

Just starting out? Need help? Post your questions and find answers here.
User avatar
Martt
User
User
Posts: 18
Joined: Sat Dec 23, 2017 4:03 pm
Location: The Netherlands

SOLVED - Why doesn't this work (round a float via a procedure) ???

Post by Martt »

Hi,

I do not understand why the following code returns #True, since it should be #False.
Not using the procedure and using a manual Round function works fine.
But this should work imho...

Hmm, Asm compiler (x86 and x64) returns #True, but C compiler (x86 and x64) returns #False). Strange.

Code: Select all

EnableExplicit

Structure Rectangle
    x.f
    y.f
    width.f
    height.f
EndStructure

Procedure.i RectangleRound(*Inout.Rectangle)

    If *Inout
        *Inout\x      = Round(*Inout\x, #PB_Round_Nearest)
        *Inout\y      = Round(*Inout\y, #PB_Round_Nearest)
        *Inout\width  = Round(*Inout\width, #PB_Round_Nearest)
        *Inout\height = Round(*Inout\height, #PB_Round_Nearest)
    EndIf

    ProcedureReturn *Inout

EndProcedure

Define Bounds.Rectangle

RectangleRound(@Bounds)
;Round(Bounds\x, #PB_Round_Nearest)
;Round(Bounds\y, #PB_Round_Nearest)

If Bounds\x And Bounds\y
    Debug "#True"
Else
    Debug "#False"
EndIf

Last edited by Martt on Sun Jul 14, 2024 12:41 pm, edited 1 time in total.
infratec
Always Here
Always Here
Posts: 7577
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Why doesn't this work (round a float via a procedure) ???

Post by infratec »

A float is not an expression.

You can do it like this:

Code: Select all

If Int(Bounds\x) And Int(Bounds\y)
Or like this (better solution)

Code: Select all

If Bounds\x <> 0 And Bounds\y <> 0
User avatar
Martt
User
User
Posts: 18
Joined: Sat Dec 23, 2017 4:03 pm
Location: The Netherlands

Re: Why doesn't this work (round a float via a procedure) ???

Post by Martt »

infratec wrote: Sun Jul 14, 2024 10:54 am A float is not an expression.

You can do it like this:

Code: Select all

If Int(Bounds\x) And Int(Bounds\y)
Or like this (better solution)

Code: Select all

If Bounds\x <> 0 And Bounds\y <> 0
I know that <> #Null works fine. But If with a zero number should always return False. I'm using that all the time, never fails. And the C compiler does return #False in my example.

Code: Select all

Define A.f = 0.0

If A
    Debug "#True"
Else
    Debug "#False"
EndIf
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Why doesn't this work (round a float via a procedure) ???

Post by mk-soft »

Always ??? :mrgreen:

Float or double values on is the same to evaluate is always bad

Code: Select all

Define A.f = 0.0

Debug PeekL(@a)

If A
    Debug "#True"
Else
    Debug "#False"
EndIf

Define A.f = -0.0

Debug PeekL(@a)

If A
    Debug "#True"
Else
    Debug "#False"
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Why doesn't this work (round a float via a procedure) ???

Post by Little John »

To get to the point:

Code: Select all

; tested with PB 6.04 LTS (x64) on Windows (ASM backend)

Define A.f = -0.0

If A              ; wrong
   Debug "True"
Else
   Debug "False"
EndIf

If A <> 0         ; correct
   Debug "True"
Else
   Debug "False"
EndIf
SMaag
Enthusiast
Enthusiast
Posts: 302
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Why doesn't this work (round a float via a procedure) ???

Post by SMaag »

It's again the genearal problem with Floats

it's generally not allowed to use floats as an expression! Would be better the compiler would not allow that!

A short time ago I went deeper into that issue.
If you do like that you might get a different result on different compilers and a different result with same compiler
on different CPU's. If you search at google you will find some articels about that problem.
Until today you will not get a compaerable result up tp the last digit with floats on different CPU's!

1. If you want to compare two floats for equal you have to use an interval!
2. Never use floats as expression like it is possible with Int

The difference betwwen PB ASM-Compiler and C-Compiler is:
PB ASM always use the Float unit (80 Bit) the C-Compilers optimize some float options and use faster MMX or SSE Version
and at MMX SSE a float is only 64-Bit.

That issue is causing some more problems in PB.
If you use an Int with >= 48Bit and do an ABS() you will get differnt results in ASM and C too.
ASM use FloatUnit ABS command and C-Compiler use MMX/SEE what cause a rounding Problem.
Under ASM you get the right value and C is wrong!


The ABS() Problem
https://www.purebasic.fr/english/viewto ... 53#p614053

Floating Point Determinism
https://gafferongames.com/post/floating ... terminism/
User avatar
Martt
User
User
Posts: 18
Joined: Sat Dec 23, 2017 4:03 pm
Location: The Netherlands

Re: Why doesn't this work (round a float via a procedure) ???

Post by Martt »

Ok, thanks for the explanations, everybody. Looks like I picked up a bad habit along the way.

In this case it kind of sucks, since I'm working on a RayLib program, and RayLib uses floats everywhere.
It's only 40K lines to check. Search If....... I need a drink.... :oops: :evil:
Post Reply