5
\$\begingroup\$

Overview:

Using you language of choice, implement a complete "half away from 0" rounding function in the shortest amount of code possible.

Rules/Constraints:

  • Direct, predefined Round-like functions are not allowed.
  • Floor/Ceiling-type functions are allowed, if your language supports these.
  • Function shall be able to handle 32-bit floating-point values.
  • Function shall be able to correctly handle negative values (see examples).
  • This is Golf, so shortest code wins.
  • Correct rounding for this challenge is to round away from 0, such that a rounded value will have an equal or larger absolute value.

Input/Output:

  • Your function shall take two parameters:
    • The first is a float x, which is the value to round.
    • The second is an integer n, which is the number of decimal places to round to.
    • x can be a whole number or contain a decimal part, fitting within a 32-bit, single-precision float.
    • n can be greater than or equal to 0, and may be larger than the number of decimal places in x.
  • Output will be the correctly rounded x.
  • *In cases where the solution is not exactly representable in IEEE float format, the output should be the logical representation you would have figured if not using a computer. i.e. The output of Round(0.125, 2) should be 0.13.

Example I/O:

Round(1.23456789, 7)
1.2345679

Round(1.234, 5)
1.234 OR 1.23400 (Your choice on trailing 0)

Round(-0.5, 0)
-1 NOT 0

Round(-0.123, 2)
-0.12 NOT -0.13

Round(3.1415926535897932384626433832, 20)
3.14159265358979323846

Winning:

**Some system limitations may be present which make your function less accurate/usable. In these cases, supply the best possible calculation you can within those limitations.

For example, I have a solution in my preferred environment, VBA in Office 2003, which only allows me to round up to 307 digits, while the IDE will only let me use values up to 15 significant decimal places. (I will eventually post this example here.)

With your answer submission, please post the highest values of n and the largest number of significant decimal digits for x for which your function will run. If you cannot meet the minimum requirements, that solution is disqualified, no matter the code length. (i.e. my own solution described above is invalid)

While this is code golf, and the shortest code will generally win. If two answers exist with different maximum values for x and n, the solution which works with the highest input values (measured as x * n) will win. If these two solutions meet the same limitation while fulfilling the requirements of the challenge, then the shortest code of those two will win.

If no solutions meet the requirement, then the best limitation score (shortest code length in the event of a tie) will win.

Example submission given the rules above for my own code:

<CODE HERE>
Max n = 307
Max x digits = 15
Limitation Score (x * n) = 4605
\$\endgroup\$
26
  • \$\begingroup\$ Ehm, you say that 15 decimal places is a limitation, and you give examples like 1.23456789, but you also say that it should handle single precision floats. So which one is it? \$\endgroup\$
    – Mr Lister
    Commented Aug 27, 2012 at 18:56
  • \$\begingroup\$ @MrLister The spec is to be able to handle Singles. For what I am able to come up with on my own, as an example only, I am personally limited to 15 characters. In other words, my own solution is not valid for this challenge. 1.23456789 is again for example only. \$\endgroup\$
    – Gaffi
    Commented Aug 27, 2012 at 18:58
  • 2
    \$\begingroup\$ What is your rounding rule for exact halves? Based on the example of -0.5 it could be away from 0 or nearest odd number; you should make it explicit because a) it's ambiguous; b) those are both weird rules. (The standard rules are half-up, half-down, or half-even). \$\endgroup\$ Commented Aug 27, 2012 at 19:13
  • \$\begingroup\$ What constitutes "correctly rounded"? \$\endgroup\$
    – ardnew
    Commented Aug 27, 2012 at 19:16
  • 2
    \$\begingroup\$ @Gaffi see: en.wikipedia.org/wiki/Rounding#Tie-breaking \$\endgroup\$
    – ardnew
    Commented Aug 27, 2012 at 19:24

4 Answers 4

2
\$\begingroup\$

Q (29 Characters)

{("i"$x*10 xexp y)%10 xexp y}

Sample usage

{("i"$x*10 xexp y)%10 xexp y}[1.23456;4]

Works by multiplying your x input by 10 to the power of your y input, casting to an int and then dividing again by 10 to the power of your y input.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Deduplicate for great savings {(6h$x*i)%i:10 xexp y}. \$\endgroup\$
    – skeevey
    Commented Sep 7, 2012 at 18:23
1
\$\begingroup\$

Python (153 chars, max(x)=infinite, max(n)=13)

You can input a float, however it works much, much better (max(n)=infinite instead of 13) if you input a string.

def Round(x,n):
    x=map(str,str(x))
    if n==0:x.remove('.')
    n+=1+(n!=0)+(x[0]=='-')
    if n<len(x):x[n-1]=str(int(x[n-1])+(x[n]>='5'))
    return''.join(x[:n])

Explanation:

x=map(str,str(x))
Seperate each character of x. (e.x. when x=5.4, running this makes x equal to ['5', '.', '4'].

if n==0:x.remove('.')
A hack to get around Test Case 3, Round(-0.5, 0). Removes the decimal so we don't get the output -1.

n+=1+(n!=0)+(x[0]=='-')
if n<len(x):x[n-1]=str(int(x[n-1])+(x[n]>='5'))

1 compensates for the decimal point. I think. (n!=0): Compensates for the removal of the decimal point and allows the next line to run.
(x[0]=='-'): Makes it so that in the next line, the negative sign (an additional character) will not mess up the calculation.

if n<len(x): Accounts for Test Case 2, Round(1.234, 5), because Python errors when you try to access the nth item of a list if it's not there. (x[5] is called in the test case, and x does not have a 6th term.)
x[n-1]=str(int(x[n-1])+(x[n]>='5')): Gets the n-1th item of x (which is a string, so it needs to be turned into a number), and adds 1 to it if the nth item of x is greater than or equal to 5. Then it gets turned back into a string.

return''.join(x[:n]): Returns the concatenation of everything up to the nth item in x.

\$\endgroup\$
5
  • \$\begingroup\$ if n==0:x.remove('.') / A hack to get around Test Case 3, Round(-0.5, 0). Removes the decimal so we don't get the output -1. But we do want -1 as the output for that test case. \$\endgroup\$
    – Gaffi
    Commented Aug 28, 2012 at 1:08
  • \$\begingroup\$ In line 4, try replacing n[0]=='-' with x[0]=='-' \$\endgroup\$
    – Matt
    Commented Aug 28, 2012 at 1:42
  • \$\begingroup\$ @Gaffi: That's -1., not -1 \$\endgroup\$
    – beary605
    Commented Aug 28, 2012 at 4:50
  • \$\begingroup\$ @Matt: Oops. I originally had my function as Round(a, b), but translated it for clarity. \$\endgroup\$
    – beary605
    Commented Aug 28, 2012 at 4:51
  • \$\begingroup\$ @beary605 Ah, I see. The period is inside the formatted string. :-) \$\endgroup\$
    – Gaffi
    Commented Aug 28, 2012 at 10:50
1
\$\begingroup\$

Python, 55 46 chars

R=lambda x,n:int(10**n*x+(.5,-.5)[x<0])/10.**n

Translates the decimal point, rounds half up using int(x+.5), then translates the decimal point back. Negative numbers use int(x-.5).

Should be as accurate as a 64-bit IEEE can get (15+ decimal digits). n can be up to about 300 or so (less if x is big).

\$\endgroup\$
5
  • \$\begingroup\$ It doesn't work when n=0. R(3.123,0) gives 3.0 instead of 3 \$\endgroup\$
    – lortabac
    Commented Aug 29, 2012 at 9:40
  • \$\begingroup\$ I think this should fix the problem (56 chars): R=lambda x,n:int(10**n*x+(.5,-.5)[x<0])/(10.,10)[n<1]**n \$\endgroup\$
    – lortabac
    Commented Aug 29, 2012 at 10:04
  • 1
    \$\begingroup\$ @lortabac: I don't understand. 3.0 and 3 are the same number. \$\endgroup\$ Commented Aug 29, 2012 at 15:13
  • \$\begingroup\$ @lortabac: Thanks for the negative number idea. \$\endgroup\$ Commented Aug 29, 2012 at 15:31
  • \$\begingroup\$ Ok, I think you are right. There are no formatting requirements in the rules. \$\endgroup\$
    – lortabac
    Commented Aug 29, 2012 at 16:02
1
\$\begingroup\$

C, 51 Characters

float round(float x, int n)
{
    return(long)(x*pow(10,n)+(x>0?0.5:-0.5))/pow(10,n);
}

Not including the function headers, it's 51 characters.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.