1. round.e
- Posted by Ad Rienks <Ad_Rienks at COMPUSERVE.COM>
Aug 11, 1998
-
Last edited Aug 12, 1998
Hello fellow Euphorians,
As a result of previous discussions about rounding numbers, I have been
experimenting and I think I found a good solution to the problem.
Rounding by cutting off, division and-or multiplication did not work for
me.
The results were often not as exact as I needed.
You should know, I=B4m in the accounting business and very strict on thes=
e
sort of things. For others like me I donate this following routine.
-- round.e, version 1.1.2, August 12, 1998
-- Ad Rienks (c) kwisoft 1998
-- donated to the Euphoria public domain
-- rounds an atom to x decimals, like a calculator
-- can be adapted to a precision of 8 decimals
-- above that, I'm not sure if precision is correct
-- bugs, comments, test results to:
-- Ad_Rienks at compuserve.com
include get.e
include graphics.e
with trace
-- trace(1)
function round2(atom a, integer p)
integer dot, negative, round
sequence format
object s, result
if integer(a) then
-- no need processing it further
return a
end if
negative =3D 0
if a < 0 then
negative =3D 1
a =3D -a
end if
-- take 2 extra decimals,
-- to avoid unwanted rounding by sprintf()
format =3D "%." & sprintf("%d", p + 2) & 'f'
s =3D sprintf(format, a)
dot =3D find('.', s)
round =3D 0
if find(s[dot + p + 1], "56789") then
round =3D 1
end if
s =3D s[1..dot + p]
result =3D value(s)
result =3D result[2]
if round then
result =3D result + power(10, -p)
end if
if negative then
result =3D - result
end if
return result
end function -- round2
---------------------------------- Tests ------------------------------
-- Test 0
? round2(100, 0)
if getc(0) then =
end if
-- Test 1
atom test
integer precision
sequence format
precision =3D 8
format =3D "%." & sprintf("%d", precision + 2) & 'f'
clear_screen()
puts(1, "\tTest 1\t('q' to quit)\n\n")
while 1 do
test =3D rand(1e9) / 1e9 - .5
printf(1, format & " rounded to %d decimals: " & format & '\n',
{test, precision, round2(test, precision)})
if wait_key() =3D 'q' then
exit
end if =
end while
-- Test 2
sequence pos
precision =3D 2
format =3D "%." & sprintf("%d", precision + 2) & 'f'
clear_screen()
puts(1, "\tTest 2\t('q' to quit)\n\n")
for n =3D -.1 to .1 by .001 do
printf(1, format & " rounded to %d decimals: " & format & '\n', =
{n, precision, round2(n, precision)})
pos =3D get_position()
if pos[1] =3D 25 then
if wait_key() =3D 'q' then
exit
end if
scroll(22, 3, 24)
position(3, 1)
end if
end for
-- Test 3
atom a, b
precision =3D 2
clear_screen()
puts(1, "\tTest 3\t('q' to quit)\n\n")
while 1 do
a =3D rand(100000) / 10000 - 5
b =3D rand(1000) / 100 - 5
printf(1, "%f x %f =3D %f (to %d decimals)\n",
{a, b, round2(a * b, precision), precision})
if wait_key() =3D 'q' then
exit
end if
end while
clear_screen()
Regards,
Ad Rienks
2. round.e
Hello,
I=B4m the first to respond to my own round2-function. U C, I tricked myse=
lf
again, a bit.
The key to this lies in the following lines
-- take 2 extra decimals,
-- to avoid unwanted rounding by sprintf()
format =3D "%." & sprintf("%d", p + 2) & 'f'
Now, if you will round 0.49495 to 2 decimals, you would like to have 0.49=
as a result,
but you get 0.50. Sprintf does that. However, if you need a greater
precision, you can acquire that by taking more extra decimals. Thought I
should report this to you.
Regards,
Ad Rienks