2
\$\begingroup\$

Challenge:

Given two inputs, x and y, round x to one less significant figure, then repeat until it has y number of unrounded digits left. (the decimal point does not count as a digit)

Input & Output

Input can be a combination of strings and integers, e.g. you can have the input as a string and the output as an int, or vice versa.
The input number will never have 15 digits total, and the y will never be greater than the input number's length and will always be greater than 0.
Example:

x = 32.64712, y = 3
    32.64712 -> 32.6471 -> 32.647 -> 32.65 -> 32.7  (Three unrounded digits left)

x = 87525, y = 2
    87525 -> 87530 -> 87500 -> 88000 (Two unrounded digits left)

x = 454, y = 3
    454 -> 454 (Three unrounded digits left)

(steps shown just to clarify, you only need to output the last value.)

Rules

  • Trailing 0's are allowed
  • 5's round up
  • Standard loopholes apply

This is , so you should strive for the shortest answer.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I take it numbers ending in 5 round up? If we get a result like 3.100, do we have to output the number with trailing zeroes? \$\endgroup\$
    – xnor
    Commented Dec 12, 2018 at 4:53
  • 3
    \$\begingroup\$ The phrase "round x's second to last digit" seems ambiguous and I'd interpret it differently from what the challenge intends. I'd call it "round away x's last digit" or "round x to one less significant figure". Also, the input refers to integers, but the numbers can be non-whole reals. \$\endgroup\$
    – xnor
    Commented Dec 12, 2018 at 5:00
  • \$\begingroup\$ @xnor Numbers ending in 5 do round up, trailing zeros are ok \$\endgroup\$
    – Gymhgy
    Commented Dec 12, 2018 at 5:10
  • \$\begingroup\$ Ugh, JavaScript rounds 32.647 to 32.64999999999999857891 which is still less than 32.65 ;-( \$\endgroup\$
    – Neil
    Commented Dec 12, 2018 at 9:47
  • \$\begingroup\$ For javascript, you can scale the number up so that there are no digits right of the decimal point, then divide it down after scaling(since integer math is exact) \$\endgroup\$
    – Gymhgy
    Commented Dec 12, 2018 at 18:19

5 Answers 5

1
\$\begingroup\$

Python 2, 101 97 92 91 85 bytes

lambda x,y:reduce((lambda n,l:int(n/.1**l+.5)*.1**l),range(15,y+~len(`int(x)`),-1),x)

Try it online!


Alternative : If Python's round would round "half up" instead of "half to even":

Python 2, 57 bytes

lambda x,y:reduce(round,range(15,y-len(`int(x)`)-1,-1),x)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 58 bytes

f=
(x,n,y=x.toPrecision(n))=>y>x?y:(x*9/8-y/8).toPrecision(n)
<div oninput=o.textContent=f(+x.value,+n.value)><input id=x><input id=n type=number min=1 max=15 value=3><pre id=o>

Arithmetic solution. The given procedure rounds numbers up if they are greater than 4/9 of the next value, so if rounding doesn't increase the number, try again with a slightly greater value.

\$\endgroup\$
0
\$\begingroup\$

Perl 6, 59 bytes

{($^a,{.round(10**($++-15))}...^0|any 10 X**^30-15)[*-$^b]}

Try it online!

Anonymous code block that takes two numbers and returns a number.

Explanation:

{                                                         }  # Anonymous code block
 (                          ...                   )  # Create a sequence
  $^a,   # With the first element as the input
      {                    }  # With each element being
       .round(10**($++-15))   # The previous element rounded by another digit
                                0                   # Until 0
                                 |                  # or
                                  any 10 X**^30-15  # Any available power of 10
                               ^  # Ignoring the last number
                                                   [*-   ]  # Index from the end
                                                      $^b   # The second number
\$\endgroup\$
0
\$\begingroup\$

R, 79 bytes

Unfortunately, R uses "round to even" when rounding off a .5

function(x,y){for(i in nchar(gsub('\\.','',x)):y){x=signif((x*100+1)/100,i)};x}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Ruby, 103 bytes

This is ugly and presumably there are better ways (alas sprintf’s %g rounds to even), but it works.

g=->m,n{m.to_s.size>n ?g[(m/10.0).round,n]:m}
->x,n{_,s,_,e=x.to_d.split
"0.#{g[s.to_i,n]}".to_f*10**e}

Attempt This Online!

\$\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.