Rounding to specific number of digits in Haskell

Philipp

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?

bheklilr

This isn't a haskell problem as much as a floating point problem. Since each floating point number is implemented in a finite number of bits, there exist numbers that can't be represented completely accurately. You can also see this by calculating 0.1 + 0.2, which awkwardly returns 0.30000000000000004 instead of 0.3. This has to do with how floating point numbers are implemented for your language and hardware architecture.

The solution is to continue using your roundTo function for doing computation (it's as accurate as you'll get without special libraries), but if you want to print it to the screen then you should use string formatting such as the Text.Printf.printf function. You can specify the number of digits to round to when converting to a string with something like

import Text.Printf

roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String
roundToStr n f = printf ("%0." ++ show n ++ "f") f

But as I mentioned, this will return a string rather than a number.

EDIT:

A better way might be

roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String
roundToStr n f = printf (printf "%%0.%df" n) f

but I haven't benchmarked to see which is actually faster. Both will work exactly the same though.

EDIT 2:

As @augustss has pointed out, you can do it even easier with just

roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String
roundToStr = printf "%0.*f"

which uses a formatting rule that I was previously unaware of.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Rounding to specific number of digits in Haskell

From Dev

PHP: rounding a number into 16 decimal digits

From Dev

PHP: rounding a number into 16 decimal digits

From Dev

Return a specific number of digits

From Dev

rounding of digits

From Dev

rounding of digits

From Dev

How to display a fixed number of digits in C++ without rounding

From Dev

Change Woocommerce order number to specific number of digits

From Dev

Change Woocommerce order number to specific number of digits

From Dev

How to create a random 16 digits number, with specific first digits?

From Dev

Rounding to n significant digits

From Dev

Rounding digits in ggpairs

From Dev

Generate random number in range without specific digits

From Dev

generate random number using specific digits in javascript

From Dev

Setting digits from a number to a specific position in an array

From Dev

How to convert string to decimal with specific number of digits

From Dev

vim search numbers containing specific number of digits

From Dev

sed - Changing pattern with specific number of digits

From Dev

convert number string into float with specific precision (without getting rounding errors)

From Dev

Rounding errors to 1 significant figure and round values according to number of digits in errors

From Dev

Regex: rounding all the real number in a text file (keeping the 15 decimal digits)

From Dev

Rounding errors to 1 significant figure and round values according to number of digits in errors

From Dev

Why doesn't Python include number of digits I specify after the decimal point when rounding?

From Dev

Printing out a specific number of digits based on the number with longest length?

From Dev

Printing out a specific number of digits based on the number with longest length?

From Dev

Rounding and trimming digits with specified precision

From Dev

Rounding Logic for decimal digits in java

From Dev

rounding to desired digits in MATLAB and C

From Dev

Rounding a float to an int in haskell

Related Related

  1. 1

    Rounding to specific number of digits in Haskell

  2. 2

    PHP: rounding a number into 16 decimal digits

  3. 3

    PHP: rounding a number into 16 decimal digits

  4. 4

    Return a specific number of digits

  5. 5

    rounding of digits

  6. 6

    rounding of digits

  7. 7

    How to display a fixed number of digits in C++ without rounding

  8. 8

    Change Woocommerce order number to specific number of digits

  9. 9

    Change Woocommerce order number to specific number of digits

  10. 10

    How to create a random 16 digits number, with specific first digits?

  11. 11

    Rounding to n significant digits

  12. 12

    Rounding digits in ggpairs

  13. 13

    Generate random number in range without specific digits

  14. 14

    generate random number using specific digits in javascript

  15. 15

    Setting digits from a number to a specific position in an array

  16. 16

    How to convert string to decimal with specific number of digits

  17. 17

    vim search numbers containing specific number of digits

  18. 18

    sed - Changing pattern with specific number of digits

  19. 19

    convert number string into float with specific precision (without getting rounding errors)

  20. 20

    Rounding errors to 1 significant figure and round values according to number of digits in errors

  21. 21

    Regex: rounding all the real number in a text file (keeping the 15 decimal digits)

  22. 22

    Rounding errors to 1 significant figure and round values according to number of digits in errors

  23. 23

    Why doesn't Python include number of digits I specify after the decimal point when rounding?

  24. 24

    Printing out a specific number of digits based on the number with longest length?

  25. 25

    Printing out a specific number of digits based on the number with longest length?

  26. 26

    Rounding and trimming digits with specified precision

  27. 27

    Rounding Logic for decimal digits in java

  28. 28

    rounding to desired digits in MATLAB and C

  29. 29

    Rounding a float to an int in haskell

HotTag

Archive