Floating Point Rounding

January 8, 2013

This is easy enough:

(define (round f n)
  (/ (truncate (+ (* f (expt 10 n)) 0.5)) (expt 10 n)))

The expression (expt 10 n) returns 1000 when n is 3, 100 when n is 2, 1 when n is 0, and 1/10 when n is -1. This number is first multiplied by f and then divided into the result, so the output has the same order as the input. In between the multiplication and the division, 0.5 is added, then the result of the addition is truncated, which has the desired rounding effect. There is no need for extra credit here; the function works perfectly well for both positive and negative n.

You can run the program at http://programmingpraxis.codepad.org/AF35jtp1.

About these ads

Pages: 1 2

11 Responses to “Floating Point Rounding”

  1. fisherro said

    I guess I should check the suggested solution to see if it is essentially the same as mine before posting mine. ^_^

  2. Abe C. said

    > javabloggi said
    >January 8, 2013 at 10:52 AM
    >
    >My Java solution here.

    Your solution does not perform rounding correctly. You seem to be checking the digit in one more significant place value than you need to be in order to determine if rounding up is needed.

    For example, from your output:
    01 Enter numbers:
    02 1000/7,3
    03 Answer: 142.858

    However, the correct answer should be 12.857.

    Here’s my java solution:

    public class FPR {

    public static double round(double f, int n) {
    double div = Math.pow(10, (double) n);
    if (div*f*10 % 10 >= 5) {
    return ((double) ((int) (div*f)) + 1)/div;
    } else {
    return ((double) ((int) (div*f)))/div;
    }
    }

    public static void main(String[] args) {
    for (int i = 3; i >= -2; i–) {
    System.out.println(“1000/7,” + i + “: ” + round(1000.0/7.0, i));
    }
    }
    }

    Thanks.

    Katzby

  3. Abe C. said

    >However, the correct answer should be 12.857.

    Sorry, I meant to say it should be 142.857.

    Thanks.

    Katzby

  4. Joe A said

    An overly complicated python version =)

    def my_round(f,n):
    	'''Round floating point f n places
    	>>> my_round(1000/7.0,3)
    	142.857
    	>>> my_round(1000/7.0,2)
    	142.86
    	>>> my_round(1000/7.0,1)
    	142.9
    	'''
    	num = int(f * 10**(n+1))
    	if num % 10 >= 5:
    		num+= 10
    	return (num/10) / 10.0**(n)
    
    
  5. javabloggi said

    >However, the correct answer should be 12.857.

    >Sorry, I meant to say it should be 142.857.

    >Thanks.

    >Katzby

    Thanks for letting me know. I corrected the mistake.

  6. ardnew said

    Every answer posted so far handles negative values incorrectly. Also, it doesn’t appear anyone implemented an unbiased tie-breaking scheme?

    This solution handles both issues correctly (tie-breaking done with round-to-even) as well as the extra credit.

    However, it doesn’t support the technical definition of significant digits.

    use strict;
    use warnings;
    
    sub round
    {
      my ($f, $n) = @_;
    
      my $m = 10 ** -$n;
      my $y = $f / $m;
    
      if (abs(abs($y) - abs(int($y))) - 0.5 < 1e-6)
      {
        return $m * 
          (int($y) + (int($y) & 1) * (-1 + 2 * ($y > 0)));
      }
      else
      {
        return int(abs($y) + 0.5) * (-$m, $m)[$y > 0];
      }
    }
    
  7. ardnew said

    oops typo on line 11. should be:

      if (abs(abs($y) - abs(int($y)) - 0.5) < 1e-6)
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 643 other followers

%d bloggers like this: