Floor()

Share your advanced PureBasic knowledge/code with the community.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Floor()

Post by Trond »

"floor- Returns the rounded value of val to specified precision (number of digits after the decimal point). precision can also be negative or zero (default). "

Code: Select all

Procedure.d Floor(Float.d, Precision.d = 0) 
  Precision = Pow(10, Precision) 
  Float * Precision 
  Float = Int(Float) 
  Float / Precision 
  ProcedureReturn Float 
EndProcedure
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Code: Select all

Macro Floor(Float,Precision=0)
  Int(Float*1E#Precision#)/1E#Precision
EndMacro

;Test it:
Debug Floor(8.8888,2)
:)
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

And a way to Round it instead to Floor it:

Code: Select all

Procedure.d RoundASM(num.d)
  !fld qword[p.v_num]
  !frndint
  ProcedureReturn
EndProcedure
Macro Round(Float,Precision=0)
  RoundASM(Float*1E#Precision#)/1E#Precision
EndMacro

;Test it:
Debug Round(8.8888,2)
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Code: Select all

Macro Floor(Float,Precision=0) 
  Int(Float*1E#Precision#)/1E#Precision 
EndMacro 

Procedure.d Floor_(Float.d, Precision.d = 0) 
  Precision = Pow(10, Precision) 
  Float * Precision 
  Float = Int(Float) 
  Float / Precision 
  ProcedureReturn Float 
EndProcedure

;Test it: 
Debug 2 / Floor(8.8888,2)
Debug 2 / Floor_(8.8888,2)
:wink:
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Post by MikeB »

Something funny here -

Code: Select all

Procedure.d RoundASM(num.d) 
  !fld qword[p.v_num] 
  !frndint 
  ProcedureReturn 
EndProcedure 
Macro Round(Float,Precision=0) 
  RoundASM(Float*1E#Precision#)/1E#Precision 
EndMacro 

;Test it: 
Debug Round(8.8888,3)

; Result = 8.8889999999999993
Surely this should give 8.889
Mike.
(I'm never going to catch up with the improvements to this program)
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Trond, that is the "problems" of Macros.
But always can be patched; use this instead:

Code: Select all

Macro Floor(Float,Precision=0)
  (Int(Float*1E#Precision#)/1E#Precision#)
EndMacro
:wink:
MikeB wrote:Something funny here -

Code: Select all

Procedure.d RoundASM(num.d) 
  !fld qword[p.v_num] 
  !frndint 
  ProcedureReturn 
EndProcedure 
Macro Round(Float,Precision=0) 
  RoundASM(Float*1E#Precision#)/1E#Precision 
EndMacro 

;Test it: 
Debug Round(8.8888,3)

; Result = 8.8889999999999993
Surely this should give 8.889
Sorry, but:
Debug 8889.0/1000
returns the same result :?
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Post by MikeB »

Yes Debug 8889.0/1000 gives the same result, but I though the Procedure was supposed to round 8.8888 to 3 places. That would be 8.889. Otherwise it would be better to convert to a string to show the result where StrD(8889/1000,3) or StrD(8.8888,3) give the correct answer without bothering with a procedure :D .
Mike.
(I'm never going to catch up with the improvements to this program)
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

MikeB wrote:Yes Debug 8889.0/1000 gives the same result, but I though the Procedure was supposed to round 8.8888 to 3 places. That would be 8.889. Otherwise it would be better to convert to a string to show the result where StrD(8889/1000,3) or StrD(8.8888,3) give the correct answer without bothering with a procedure :D .
Yes, but i think that is not a clean solution. :?
I don't find a clean and elegant solution for it.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Hmm!

This seems to behave correct:

Code: Select all

Procedure.d RoundASM(num.d)
  !fld qword[p.v_num]
  !frndint
  ProcedureReturn
EndProcedure
Macro Round(Float,Precision=0)
  RoundASM(Float*1E#Precision#)
EndMacro

;Test it:
Debug Round(8.8888,3)

; Result = 8.889 
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Post by va!n »

@Resactor:
Result here = 8889.0
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »


"floor- Returns the rounded value of val to specified precision (number of digits after the decimal point). precision can also be negative or zero (default). "
Where does this definition come from? That's not what FLOOR usually does.
FLOOR(x) will usually round toward -infinity so FLOOR(8.888) should be 8.
If you're going to have some specified digits after the point then I'd expect FLOOR(8.888,2) to give 8.88 and FLOOR(-8.888,2) to give -8.89


Usually ROUND rounds to nearest, CEIL rounds up and FLOOR rounds down.
FLOOR is not ROUND.

Paul.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

I saw the definition in the coding questions forum. I agree, it's not the correct function name, but I couldn't think of something better as Round() is already taken by PB.
User avatar
Michael Vogel
Addict
Addict
Posts: 2806
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Trond wrote:I saw the definition in the coding questions forum. I agree, it's not the correct function name, but I couldn't think of something better as Round() is already taken by PB.
What's about Around() ? :)
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Nah, just change the topic to "Really Round()" :lol:

Anyway, Fred needs to add anoither flag to Round()
2 = Round to nearest.

This would keep compatibility of older sources.
(Personally I'd prefer 0 doing this but....)

And maybe in addition also add a optional precision similar to the example above.

Hmm! Isn't there a feature request thread about this?
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

I found this interesting routine that seems to round correctly. However, I only tested for a few numbers. Anyone care to test more?

Code: Select all

Structure s_Round
   StructureUnion
      ;
      i.q
      u.q
      f.d
      ;
   EndStructureUnion
EndStructure
Procedure.l Round2(Value.d)
   ;
   Protected temp.s_Round
   ;
   temp\f = Value + 6755399441055744.0
   ;
   ProcedureReturn temp\u
   ;
EndProcedure
Debug Round2(328569072.31)
Debug Round2(328569072.51)
Apparently from Agner Fog's optimization routines at http://www.agner.org/assem

I haven't tested it for speed but I think it should be pretty quick.
Post Reply