Re: Limiting Decimal Places in a Floating Variable?
Re: Limiting Decimal Places in a Floating Variable?
- Subject: Re: Limiting Decimal Places in a Floating Variable?
- From: Nigel Garvey <email@hidden>
- Date: Fri, 24 Nov 2000 13:40:25 +0000
Michelle Steiner wrote on Thu, 23 Nov 2000 10:26:42 -0800:
>
On 11/23/00 3:34 AM, Nigel Garvey <email@hidden> wrote:
>
>
>>set x to -2134.2399999
>
>>set x to (round (x * 100) rounding toward zero) / 100
>
>
>
>Just out of curiosity, does this work with the number 8348.39 on your
>
>machine? Or 8348.29?
>
>
Sadly, no, it doesn't work with either of them.
OK. The following is the string-return routine from a set of rounding
handlers I've been sitting on for the past couple of weeks. Watch out for
line wraps.
(* Truncate n to d decimal places, result as string,
with or without rounding and/or padding with trailing zeros.
Believed to be immune to floating point representation errors. *)
on trncAsStr from n onto d given rounding:rounding, padding:padding
-- the decimal point character on this machine
set dpChr to the middle character of ((1 / 2) as string)
tell n * (10 ^ d)
if rounding then
it div 0.5 - it div 1 -- round off
else
it div 1 -- truncate
end if
end tell
set s to numToStr(result) -- convert to text *here*
-- insert the decimal point and deal with trailing zeros as required
if d > 0 then
set i to -1
if not padding then
repeat while character i of s is "0" and i is not -d
set i to i - 1
end repeat
end if
set s to text 1 thru -(d + 1) of s & dpChr & text -d thru i of s
else
if d < 0 then -- negative values of d work too!
if s is "0" then set d to d + 1
set s to s & text 1 thru -d of "000000000000000"
end if
-- Make integer results (d <= 0) look like reals if padding is set
if padding then set s to s & dpChr & "0"
end if
s
end trncAsStr
(* Return a number as string, transcribing from exponential notation
to long form if necessary.
Whole numbers returned looking like integers. *)
on numToStr(n)
-- the decimal point character on this machine
set dpChr to the middle character of ((1 / 2) as string)
set zeroStr to "0" & dpChr & "000000000000000000000000000000"
set s to n as string
if s contains "E" then
if n < 0 then set s to text 2 thru -1 of s -- lose any minus sign for
now
set mtLen to (count word 1 of s) - 1 -- the mantissa length
set chrList to characters 1 thru mtLen of s -- the mantissa characters
set item 2 of chrList to "" -- zap the decimal point
-- the target decimal point position (2 + exponent)
set dpPos to 2 + (text (mtLen + 2) thru -1 of s)
if dpPos > 1 then -- positive exponent
if dpPos comes after mtLen then -- append zeros
set the end of chrList to text 3 thru (2 + dpPos - mtLen) of
zeroStr
else if dpPos comes before mtLen then
-- insert a decimal point (allowing for displacement from empty
item 2)
set item dpPos of chrList to (item dpPos of chrList) & dpChr
end if -- do nothing if dpPos = mtLen
else -- negative exponent
if the last item of chrList is "0" then set the last item of
chrList to ""
set the beginning of chrList to text 1 thru (3 - dpPos) of zeroStr
end if
if n < 0 then set the beginning of chrList to "-" -- restore any
minus sign
set s to chrList as string
else
if s ends with (text 2 thru 3 of zeroStr) then set s to text 1 thru
-3 of s
end if
return s
end numToStr
trncAsStr from 8384.39 onto 2 with rounding and padding -- or without
--> "8384.39" -- (not "8384.389999999999")
trncAsStr from 123.496 onto 2 with rounding and padding
--> "123.50"
trncAsStr from 8384.39 onto -2 with rounding without padding
--> "8400"
trncAsStr from 8384.39 onto -2 with rounding and padding
--> "8400.0"
NG