I am trying to make a function to round a floating point number to a defined length of digits. What I have come up with so far is this:
import Numeric;
digs :: Integral x => x -> [x] <br>
digs 0 = [] <br>
digs x = digs (x `div` 10) ++ [x `mod` 10]
roundTo x t = let d = length $ digs $ round x <br>
roundToMachine x t = (fromInteger $ round $ x * 10^^t) * 10^^(-t)
in roundToMachine x (t - d)
I am using the digs
function to determine the number of digits before the comma to optimize the input value (i.e. move everything past the comma, so 1.234
becomes 0.1234 * 10^1
)
The roundTo
function seems to work for most input, however for some inputs I get strange results, e.g. roundTo 1.0014 4
produces 1.0010000000000001
instead of 1.001
.
The problem in this example is caused by calculating 1001 * 1.0e-3
(which returns 1.0010000000000001
)
Is this simply a problem in the number representation of Haskell I have to live with or is there a better way to round a floating point number to a specific length of digits?
You can get approximately what you want by multiplying by 1e6 , rounding to the nearest integer, and dividing by 1e6 .
Rounding is a process to estimate a particular number in a context. To round a number look at the next digit in the right place, if the digit is less than 5, round down and if the digit is 5 or more than 5, round up.
If the digit is a five or greater, you round the target digit up by one. Otherwise, you leave the target as it is. Then you replace any digits to the right with zeroes (if they are to the left of the decimal point) or else you delete the digits (if they are past the decimal point).
Rounding Addition You would add (or subtract) the numbers as usual, but then you would round the answer to the same decimal place as the least-accurate number.
I realise this question was posted almost 2 years back, but I thought I'd have a go at an answer that didn't require a string conversion.
-- x : number you want rounded, n : number of decimal places you want...
truncate' :: Double -> Int -> Double
truncate' x n = (fromIntegral (floor (x * t))) / t
where t = 10^n
-- How to answer your problem...
λ truncate' 1.0014 3
1.001
-- 2 digits of a recurring decimal please...
λ truncate' (1/3) 2
0.33
-- How about 6 digits of pi?
λ truncate' pi 6
3.141592
I've not tested it thoroughly, so if you find numbers this doesn't work for let me know!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With