Page 1 of 2

Floor()

Posted: Thu Jun 15, 2006 4:36 pm
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

Posted: Fri Jun 16, 2006 11:26 am
by Psychophanta

Code: Select all

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

;Test it:
Debug Floor(8.8888,2)
:)

Posted: Fri Jun 16, 2006 12:08 pm
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)

Posted: Fri Jun 16, 2006 2:57 pm
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:

Posted: Fri Jun 16, 2006 3:29 pm
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

Posted: Fri Jun 16, 2006 3:49 pm
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 :?

Posted: Fri Jun 16, 2006 5:14 pm
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 .

Posted: Fri Jun 16, 2006 8:54 pm
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.

Posted: Mon Jun 19, 2006 11:20 pm
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 

Posted: Tue Jun 20, 2006 12:52 am
by va!n
@Resactor:
Result here = 8889.0

Posted: Tue Jun 20, 2006 1:16 am
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.

Posted: Tue Jun 20, 2006 8:04 am
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.

Posted: Tue Jun 20, 2006 1:44 pm
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() ? :)

Posted: Wed Jun 21, 2006 7:34 am
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?

Posted: Fri Dec 29, 2006 6:10 pm
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.