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)

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
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

.
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

.
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()"
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.