Satisfying Rounding
$begingroup$
Satisfying Rounding
You know when you're in science class, and asked to round to 2 sig figs, but your answer is 5.2501...? You should round to 5.3, but that's just so unsatisfying! By rounding to 5.3, you're off by a whole 0.05, which is a large amount compared to 0.1 (the place value you're rounding to)! So help me round in a satisfying way.
To round in a satisfying way, you must round at the first digit you come across that produces a relatively small error - less than half of the maximum error possible when rounding. Basically, you need to round whenever you encounter 0, 1, 8, or 9. If that never happens, return the input as is. Do not round on leading zeroes or ones - that just doesn't feel satisfying.
Input
A string or float value that represents a nonnegative decimal number.
Output
The same decimal number rounded satisfactorily, in either string or float format.
Examples
Input -> Output
0 -> 0
0.5 -> 0.5
0.19 -> 0
0.8 -> 1
5.64511 -> 5.645
18.913 -> 20
88.913 -> 100
36.38299 -> 36.4
621 -> 620
803.22 -> 1000
547.4726 -> 547.4726
This is a code-golf challenge, so shortest code wins!
code-golf number rational-numbers
$endgroup$
|
show 5 more comments
$begingroup$
Satisfying Rounding
You know when you're in science class, and asked to round to 2 sig figs, but your answer is 5.2501...? You should round to 5.3, but that's just so unsatisfying! By rounding to 5.3, you're off by a whole 0.05, which is a large amount compared to 0.1 (the place value you're rounding to)! So help me round in a satisfying way.
To round in a satisfying way, you must round at the first digit you come across that produces a relatively small error - less than half of the maximum error possible when rounding. Basically, you need to round whenever you encounter 0, 1, 8, or 9. If that never happens, return the input as is. Do not round on leading zeroes or ones - that just doesn't feel satisfying.
Input
A string or float value that represents a nonnegative decimal number.
Output
The same decimal number rounded satisfactorily, in either string or float format.
Examples
Input -> Output
0 -> 0
0.5 -> 0.5
0.19 -> 0
0.8 -> 1
5.64511 -> 5.645
18.913 -> 20
88.913 -> 100
36.38299 -> 36.4
621 -> 620
803.22 -> 1000
547.4726 -> 547.4726
This is a code-golf challenge, so shortest code wins!
code-golf number rational-numbers
$endgroup$
$begingroup$
Sandbox
$endgroup$
– Quintec
Dec 8 '18 at 15:11
$begingroup$
Are strings such as036.40000considered a valid output?
$endgroup$
– Arnauld
Dec 8 '18 at 16:08
1
$begingroup$
Can we assume that a.0part will be given for integers? Also,0isn't positive.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 16:08
$begingroup$
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
$endgroup$
– Quintec
Dec 8 '18 at 17:03
1
$begingroup$
So19rounds to20but0.19rounds to0? Why?
$endgroup$
– Neil
Dec 8 '18 at 19:38
|
show 5 more comments
$begingroup$
Satisfying Rounding
You know when you're in science class, and asked to round to 2 sig figs, but your answer is 5.2501...? You should round to 5.3, but that's just so unsatisfying! By rounding to 5.3, you're off by a whole 0.05, which is a large amount compared to 0.1 (the place value you're rounding to)! So help me round in a satisfying way.
To round in a satisfying way, you must round at the first digit you come across that produces a relatively small error - less than half of the maximum error possible when rounding. Basically, you need to round whenever you encounter 0, 1, 8, or 9. If that never happens, return the input as is. Do not round on leading zeroes or ones - that just doesn't feel satisfying.
Input
A string or float value that represents a nonnegative decimal number.
Output
The same decimal number rounded satisfactorily, in either string or float format.
Examples
Input -> Output
0 -> 0
0.5 -> 0.5
0.19 -> 0
0.8 -> 1
5.64511 -> 5.645
18.913 -> 20
88.913 -> 100
36.38299 -> 36.4
621 -> 620
803.22 -> 1000
547.4726 -> 547.4726
This is a code-golf challenge, so shortest code wins!
code-golf number rational-numbers
$endgroup$
Satisfying Rounding
You know when you're in science class, and asked to round to 2 sig figs, but your answer is 5.2501...? You should round to 5.3, but that's just so unsatisfying! By rounding to 5.3, you're off by a whole 0.05, which is a large amount compared to 0.1 (the place value you're rounding to)! So help me round in a satisfying way.
To round in a satisfying way, you must round at the first digit you come across that produces a relatively small error - less than half of the maximum error possible when rounding. Basically, you need to round whenever you encounter 0, 1, 8, or 9. If that never happens, return the input as is. Do not round on leading zeroes or ones - that just doesn't feel satisfying.
Input
A string or float value that represents a nonnegative decimal number.
Output
The same decimal number rounded satisfactorily, in either string or float format.
Examples
Input -> Output
0 -> 0
0.5 -> 0.5
0.19 -> 0
0.8 -> 1
5.64511 -> 5.645
18.913 -> 20
88.913 -> 100
36.38299 -> 36.4
621 -> 620
803.22 -> 1000
547.4726 -> 547.4726
This is a code-golf challenge, so shortest code wins!
code-golf number rational-numbers
code-golf number rational-numbers
edited Dec 9 '18 at 20:42
Quintec
asked Dec 8 '18 at 15:10
QuintecQuintec
1,4881722
1,4881722
$begingroup$
Sandbox
$endgroup$
– Quintec
Dec 8 '18 at 15:11
$begingroup$
Are strings such as036.40000considered a valid output?
$endgroup$
– Arnauld
Dec 8 '18 at 16:08
1
$begingroup$
Can we assume that a.0part will be given for integers? Also,0isn't positive.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 16:08
$begingroup$
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
$endgroup$
– Quintec
Dec 8 '18 at 17:03
1
$begingroup$
So19rounds to20but0.19rounds to0? Why?
$endgroup$
– Neil
Dec 8 '18 at 19:38
|
show 5 more comments
$begingroup$
Sandbox
$endgroup$
– Quintec
Dec 8 '18 at 15:11
$begingroup$
Are strings such as036.40000considered a valid output?
$endgroup$
– Arnauld
Dec 8 '18 at 16:08
1
$begingroup$
Can we assume that a.0part will be given for integers? Also,0isn't positive.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 16:08
$begingroup$
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
$endgroup$
– Quintec
Dec 8 '18 at 17:03
1
$begingroup$
So19rounds to20but0.19rounds to0? Why?
$endgroup$
– Neil
Dec 8 '18 at 19:38
$begingroup$
Sandbox
$endgroup$
– Quintec
Dec 8 '18 at 15:11
$begingroup$
Sandbox
$endgroup$
– Quintec
Dec 8 '18 at 15:11
$begingroup$
Are strings such as
036.40000 considered a valid output?$endgroup$
– Arnauld
Dec 8 '18 at 16:08
$begingroup$
Are strings such as
036.40000 considered a valid output?$endgroup$
– Arnauld
Dec 8 '18 at 16:08
1
1
$begingroup$
Can we assume that a
.0 part will be given for integers? Also, 0 isn't positive.$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 16:08
$begingroup$
Can we assume that a
.0 part will be given for integers? Also, 0 isn't positive.$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 16:08
$begingroup$
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
$endgroup$
– Quintec
Dec 8 '18 at 17:03
$begingroup$
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
$endgroup$
– Quintec
Dec 8 '18 at 17:03
1
1
$begingroup$
So
19 rounds to 20 but 0.19 rounds to 0? Why?$endgroup$
– Neil
Dec 8 '18 at 19:38
$begingroup$
So
19 rounds to 20 but 0.19 rounds to 0? Why?$endgroup$
– Neil
Dec 8 '18 at 19:38
|
show 5 more comments
7 Answers
7
active
oldest
votes
$begingroup$
JavaScript (ES6), 100 99 98 78 bytes
Takes input as a string. Returns a float.
s=>+(0+s).replace(/d/g,(d,i)=>j&&+d+((n=s[i+!++s[i]])<2&&i?--j:n>7&&j--),j=1)
Try it online!
How?
We first prepend a leading $0$ to the input string, so that we're guaranteed to have a digit before a possible leading $8$ or $9$, that must trigger the rounding right away.
The flag $j$ is set to $1$ as long as we are looking for a digit on which we can do a satisfying rounding, and set to $0$ afterwards.
Because a leading $0$ was added to the string that we're walking through but $s$ was left unchanged, $d$ contains the current character and $s[i]$ is pointing to the next character.
We use the following code to load the next digit in $n$, skipping a possible decimal separator:
n = s[i + !++s[i]]
Although strings are immutable in JavaScript, the expression ++s[i] will return $s[i]+1$ if it contains a numeric value, even though $s[i]$ is not actually incremented. Therefore, the expression !++s[i] is evaluated to $false$ (coerced to $0$) for all digits (including $0$) and to $true$ (coerced to $1$) for the decimal separator ".".
When the rounding occurs, we yield d + --j if the next digit $n$ is $0$ or $1$ (and it's not the leading digit of the original input) and d + j-- if $n$ is $8$ or $9$. Therefore, $j$ is set to $0$ in both cases but we add $0$ to $d$ in the first case (rounding down) and $1$ in the second case (rounding up).
$endgroup$
1
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
add a comment |
$begingroup$
Ruby, 79 77 69 67 65 bytes
->n,z=n+".0"{z[i=z=~/./]='';n.to_f.round (z=~/(?!^)[01]|8|9/)-i}
Try it online!
Explanation
->nTake input as a string
z=n+".0"Create a temporary stringzthat is guaranteed to contain a dot and a relevant digit.
i=z=~/./Determine the position of the decimal dot inzand assign toi.
z[i]=''Drop the dot so that it doesn't get in the way further on.
z=~/(?!^)[01]|8|9/Determine the position of non-starting0-1or any8-9, whichever comes first.
(...)-iThis difference will be the number of decimal places to keep, negative if we will be rounding left of the dot.
n.to_f.round ...Convert to float and do the rounding.
$endgroup$
add a comment |
$begingroup$
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
$endgroup$
$begingroup$
WhyŒV? I thinkVwill work too.
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
Oh, because it's not acting on the input? Try_>¥0ɓVærlike mine is (I missed usage of the dyadic quick so thanks too!)
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
add a comment |
$begingroup$
Jelly, 30 29 bytes
-1 thanks to Erik the Outgolfer (use of dyadic quick ¥ from his answer)
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær
A monadic link accepting a list of characters which yields a float.
Try it online! Or see the test-suite.
How
First note that the input string is made exclusively from the characters 0123456789. which have ordinals [48,49,50,51,52,53,54,55,56,57,46], which have remainders when divided by eight of [0,1,2,3,4,5,6,7,0,1,6]. The only characters which are between -1 and 1 inclusive are 0, 1, 8, and 9.
Furthermore if we subtract eight from the ordinals ([40,41,42,43,44,45,46,47,48,49,38]) the same (fairly obviously) holds. If we halve these ([20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) the only characters which have remainders when divided by eight which are between -1 and 1 inclusive are 8 and 9.
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær - Link: list of characters, S
O - ordinal (vectorises across S)
;0 - concatenate a zero
- (to cater BOTH for no '0', '1', '8', or '9' AND for no '.')
µ - start a new monadic link (call that X)
_8 - subtract eight (vectorises across X)
¦ - sparse application...
1 - ...to: indices: one
H - ...do: halve (i.e. halve first ordinal)
%8 - modulo by eight (vectorises)
Ị - insignificant (abs(v)<=1?) (vectorises)
T - truthy indices
Ḣ - head
Ɗ - last three links as a monad (i.e. f(X)):
<48 - less than 48? (i.e. was it a '.' in S or the added 0?)
T - truthy indices
Ḣ - head
_ - subtract
¥ - last two links as a dyad
< 0 - less than zero? (1 if so 0 otherwise)
_ - subtract
ɓ - start a new dyadic chain (i.e. f(S,X))
V - evaluate S as Jelly code (i.e. get S as a float)
ær - round to the nearest multiple of 10^(-X)
$endgroup$
add a comment |
$begingroup$
Retina 0.8.2, 75 bytes
^[89]
10
T`d`0`(?<=.)[01].*|(?<=8|9).*
T`89d`0d`..?[89]
(.|(..+?))0+$
$2
Try it online! Link includes test cases. Explanation:
^[89]
10
Handle the case of a leading 8 or 9.
T`d`0`(?<=.)[01].*|(?<=8|9).*
If there's a non-leading 0 or 1, then zero it and the rest of the string out. Also, if there's an 8 or 9, then leave it, but zero out the rest of the string. (But leave the decimal point unchanged in either case.)
T`89d`0d`..?[89]
If there's still an 8 or a 9 at this point, then zero it out, and increment the preceding digit (possibly before the decimal point).
(.|(..+?))0+$
$2
Delete trailing zeros if they are after a decimal point, but only delete the decimal point if there are no other digits in between.
$endgroup$
add a comment |
$begingroup$
C (gcc), 111 102 bytes
g(_,i,j,k)char*_;{for(i=*_<56?*_++:48,j=3;j;j&=k%8>1|(i=*_++)/48*2)putchar(j&1?i+(k=_[*_<48])/56:48);}
Try it online!
//_: input, as string
//i: current digit, rounded if applicable
//j: tracks whether number is rounded, and whether or '.' has been encountered
//k: digit to test rounding (round if k is one of 0,1,8,9)
//'0'==48, '8'==56
g(_,i,j,k)char*_;{
for(i=*_<56?*_++:48,j=3; //special case: if first digit is 8 or 9, use a
//placeholder digit with value 0. initialize j.
j; //only stop execution when number is rounded and
//'.' or has been encountered.
j&=k%8>1|(i=*_++)/48*2) //check if execution should stop.
putchar(j&1?i+(k=_[*_<48])/56:48); //print '0' if rounding had already been done;
//otherwise, print digit. round up as needed.
}
$endgroup$
add a comment |
$begingroup$
C# (Visual C# Interactive Compiler), 280 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=decimal.Parse(c);Func<decimal>q=()=>(decimal)Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!
It can be shorter if I used doubles instead of decimals, but I used decimals to preserve accuracy, or else a number like 547.4726 would be 547.472595214844.
C# (Visual C# Interactive Compiler), 268 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=float.Parse(c);Func<double>q=()=>Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!(Less accurate version)
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "200"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f177203%2fsatisfying-rounding%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
JavaScript (ES6), 100 99 98 78 bytes
Takes input as a string. Returns a float.
s=>+(0+s).replace(/d/g,(d,i)=>j&&+d+((n=s[i+!++s[i]])<2&&i?--j:n>7&&j--),j=1)
Try it online!
How?
We first prepend a leading $0$ to the input string, so that we're guaranteed to have a digit before a possible leading $8$ or $9$, that must trigger the rounding right away.
The flag $j$ is set to $1$ as long as we are looking for a digit on which we can do a satisfying rounding, and set to $0$ afterwards.
Because a leading $0$ was added to the string that we're walking through but $s$ was left unchanged, $d$ contains the current character and $s[i]$ is pointing to the next character.
We use the following code to load the next digit in $n$, skipping a possible decimal separator:
n = s[i + !++s[i]]
Although strings are immutable in JavaScript, the expression ++s[i] will return $s[i]+1$ if it contains a numeric value, even though $s[i]$ is not actually incremented. Therefore, the expression !++s[i] is evaluated to $false$ (coerced to $0$) for all digits (including $0$) and to $true$ (coerced to $1$) for the decimal separator ".".
When the rounding occurs, we yield d + --j if the next digit $n$ is $0$ or $1$ (and it's not the leading digit of the original input) and d + j-- if $n$ is $8$ or $9$. Therefore, $j$ is set to $0$ in both cases but we add $0$ to $d$ in the first case (rounding down) and $1$ in the second case (rounding up).
$endgroup$
1
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
add a comment |
$begingroup$
JavaScript (ES6), 100 99 98 78 bytes
Takes input as a string. Returns a float.
s=>+(0+s).replace(/d/g,(d,i)=>j&&+d+((n=s[i+!++s[i]])<2&&i?--j:n>7&&j--),j=1)
Try it online!
How?
We first prepend a leading $0$ to the input string, so that we're guaranteed to have a digit before a possible leading $8$ or $9$, that must trigger the rounding right away.
The flag $j$ is set to $1$ as long as we are looking for a digit on which we can do a satisfying rounding, and set to $0$ afterwards.
Because a leading $0$ was added to the string that we're walking through but $s$ was left unchanged, $d$ contains the current character and $s[i]$ is pointing to the next character.
We use the following code to load the next digit in $n$, skipping a possible decimal separator:
n = s[i + !++s[i]]
Although strings are immutable in JavaScript, the expression ++s[i] will return $s[i]+1$ if it contains a numeric value, even though $s[i]$ is not actually incremented. Therefore, the expression !++s[i] is evaluated to $false$ (coerced to $0$) for all digits (including $0$) and to $true$ (coerced to $1$) for the decimal separator ".".
When the rounding occurs, we yield d + --j if the next digit $n$ is $0$ or $1$ (and it's not the leading digit of the original input) and d + j-- if $n$ is $8$ or $9$. Therefore, $j$ is set to $0$ in both cases but we add $0$ to $d$ in the first case (rounding down) and $1$ in the second case (rounding up).
$endgroup$
1
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
add a comment |
$begingroup$
JavaScript (ES6), 100 99 98 78 bytes
Takes input as a string. Returns a float.
s=>+(0+s).replace(/d/g,(d,i)=>j&&+d+((n=s[i+!++s[i]])<2&&i?--j:n>7&&j--),j=1)
Try it online!
How?
We first prepend a leading $0$ to the input string, so that we're guaranteed to have a digit before a possible leading $8$ or $9$, that must trigger the rounding right away.
The flag $j$ is set to $1$ as long as we are looking for a digit on which we can do a satisfying rounding, and set to $0$ afterwards.
Because a leading $0$ was added to the string that we're walking through but $s$ was left unchanged, $d$ contains the current character and $s[i]$ is pointing to the next character.
We use the following code to load the next digit in $n$, skipping a possible decimal separator:
n = s[i + !++s[i]]
Although strings are immutable in JavaScript, the expression ++s[i] will return $s[i]+1$ if it contains a numeric value, even though $s[i]$ is not actually incremented. Therefore, the expression !++s[i] is evaluated to $false$ (coerced to $0$) for all digits (including $0$) and to $true$ (coerced to $1$) for the decimal separator ".".
When the rounding occurs, we yield d + --j if the next digit $n$ is $0$ or $1$ (and it's not the leading digit of the original input) and d + j-- if $n$ is $8$ or $9$. Therefore, $j$ is set to $0$ in both cases but we add $0$ to $d$ in the first case (rounding down) and $1$ in the second case (rounding up).
$endgroup$
JavaScript (ES6), 100 99 98 78 bytes
Takes input as a string. Returns a float.
s=>+(0+s).replace(/d/g,(d,i)=>j&&+d+((n=s[i+!++s[i]])<2&&i?--j:n>7&&j--),j=1)
Try it online!
How?
We first prepend a leading $0$ to the input string, so that we're guaranteed to have a digit before a possible leading $8$ or $9$, that must trigger the rounding right away.
The flag $j$ is set to $1$ as long as we are looking for a digit on which we can do a satisfying rounding, and set to $0$ afterwards.
Because a leading $0$ was added to the string that we're walking through but $s$ was left unchanged, $d$ contains the current character and $s[i]$ is pointing to the next character.
We use the following code to load the next digit in $n$, skipping a possible decimal separator:
n = s[i + !++s[i]]
Although strings are immutable in JavaScript, the expression ++s[i] will return $s[i]+1$ if it contains a numeric value, even though $s[i]$ is not actually incremented. Therefore, the expression !++s[i] is evaluated to $false$ (coerced to $0$) for all digits (including $0$) and to $true$ (coerced to $1$) for the decimal separator ".".
When the rounding occurs, we yield d + --j if the next digit $n$ is $0$ or $1$ (and it's not the leading digit of the original input) and d + j-- if $n$ is $8$ or $9$. Therefore, $j$ is set to $0$ in both cases but we add $0$ to $d$ in the first case (rounding down) and $1$ in the second case (rounding up).
edited Dec 9 '18 at 17:26
answered Dec 8 '18 at 16:06
ArnauldArnauld
73.5k689309
73.5k689309
1
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
add a comment |
1
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
1
1
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
$begingroup$
And the pinball/rubber ball falls into a ditch! :)
$endgroup$
– Quintec
Dec 8 '18 at 20:17
add a comment |
$begingroup$
Ruby, 79 77 69 67 65 bytes
->n,z=n+".0"{z[i=z=~/./]='';n.to_f.round (z=~/(?!^)[01]|8|9/)-i}
Try it online!
Explanation
->nTake input as a string
z=n+".0"Create a temporary stringzthat is guaranteed to contain a dot and a relevant digit.
i=z=~/./Determine the position of the decimal dot inzand assign toi.
z[i]=''Drop the dot so that it doesn't get in the way further on.
z=~/(?!^)[01]|8|9/Determine the position of non-starting0-1or any8-9, whichever comes first.
(...)-iThis difference will be the number of decimal places to keep, negative if we will be rounding left of the dot.
n.to_f.round ...Convert to float and do the rounding.
$endgroup$
add a comment |
$begingroup$
Ruby, 79 77 69 67 65 bytes
->n,z=n+".0"{z[i=z=~/./]='';n.to_f.round (z=~/(?!^)[01]|8|9/)-i}
Try it online!
Explanation
->nTake input as a string
z=n+".0"Create a temporary stringzthat is guaranteed to contain a dot and a relevant digit.
i=z=~/./Determine the position of the decimal dot inzand assign toi.
z[i]=''Drop the dot so that it doesn't get in the way further on.
z=~/(?!^)[01]|8|9/Determine the position of non-starting0-1or any8-9, whichever comes first.
(...)-iThis difference will be the number of decimal places to keep, negative if we will be rounding left of the dot.
n.to_f.round ...Convert to float and do the rounding.
$endgroup$
add a comment |
$begingroup$
Ruby, 79 77 69 67 65 bytes
->n,z=n+".0"{z[i=z=~/./]='';n.to_f.round (z=~/(?!^)[01]|8|9/)-i}
Try it online!
Explanation
->nTake input as a string
z=n+".0"Create a temporary stringzthat is guaranteed to contain a dot and a relevant digit.
i=z=~/./Determine the position of the decimal dot inzand assign toi.
z[i]=''Drop the dot so that it doesn't get in the way further on.
z=~/(?!^)[01]|8|9/Determine the position of non-starting0-1or any8-9, whichever comes first.
(...)-iThis difference will be the number of decimal places to keep, negative if we will be rounding left of the dot.
n.to_f.round ...Convert to float and do the rounding.
$endgroup$
Ruby, 79 77 69 67 65 bytes
->n,z=n+".0"{z[i=z=~/./]='';n.to_f.round (z=~/(?!^)[01]|8|9/)-i}
Try it online!
Explanation
->nTake input as a string
z=n+".0"Create a temporary stringzthat is guaranteed to contain a dot and a relevant digit.
i=z=~/./Determine the position of the decimal dot inzand assign toi.
z[i]=''Drop the dot so that it doesn't get in the way further on.
z=~/(?!^)[01]|8|9/Determine the position of non-starting0-1or any8-9, whichever comes first.
(...)-iThis difference will be the number of decimal places to keep, negative if we will be rounding left of the dot.
n.to_f.round ...Convert to float and do the rounding.
edited Dec 9 '18 at 18:34
answered Dec 8 '18 at 16:46
Kirill L.Kirill L.
3,8151319
3,8151319
add a comment |
add a comment |
$begingroup$
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
$endgroup$
$begingroup$
WhyŒV? I thinkVwill work too.
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
Oh, because it's not acting on the input? Try_>¥0ɓVærlike mine is (I missed usage of the dyadic quick so thanks too!)
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
add a comment |
$begingroup$
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
$endgroup$
$begingroup$
WhyŒV? I thinkVwill work too.
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
Oh, because it's not acting on the input? Try_>¥0ɓVærlike mine is (I missed usage of the dyadic quick so thanks too!)
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
add a comment |
$begingroup$
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
$endgroup$
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
edited Dec 8 '18 at 18:27
answered Dec 8 '18 at 16:23
Erik the OutgolferErik the Outgolfer
31.6k429103
31.6k429103
$begingroup$
WhyŒV? I thinkVwill work too.
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
Oh, because it's not acting on the input? Try_>¥0ɓVærlike mine is (I missed usage of the dyadic quick so thanks too!)
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
add a comment |
$begingroup$
WhyŒV? I thinkVwill work too.
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
Oh, because it's not acting on the input? Try_>¥0ɓVærlike mine is (I missed usage of the dyadic quick so thanks too!)
$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
$begingroup$
Why
ŒV? I think V will work too.$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
Why
ŒV? I think V will work too.$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:15
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
@JonathanAllan Nope. (basically banker's rounding quirks)
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:16
$begingroup$
Oh, because it's not acting on the input? Try
_>¥0ɓVær like mine is (I missed usage of the dyadic quick so thanks too!)$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
Oh, because it's not acting on the input? Try
_>¥0ɓVær like mine is (I missed usage of the dyadic quick so thanks too!)$endgroup$
– Jonathan Allan
Dec 8 '18 at 18:24
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
$begingroup$
@JonathanAllan Ah, clever usage of chains, thanks.
$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 18:27
add a comment |
$begingroup$
Jelly, 30 29 bytes
-1 thanks to Erik the Outgolfer (use of dyadic quick ¥ from his answer)
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær
A monadic link accepting a list of characters which yields a float.
Try it online! Or see the test-suite.
How
First note that the input string is made exclusively from the characters 0123456789. which have ordinals [48,49,50,51,52,53,54,55,56,57,46], which have remainders when divided by eight of [0,1,2,3,4,5,6,7,0,1,6]. The only characters which are between -1 and 1 inclusive are 0, 1, 8, and 9.
Furthermore if we subtract eight from the ordinals ([40,41,42,43,44,45,46,47,48,49,38]) the same (fairly obviously) holds. If we halve these ([20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) the only characters which have remainders when divided by eight which are between -1 and 1 inclusive are 8 and 9.
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær - Link: list of characters, S
O - ordinal (vectorises across S)
;0 - concatenate a zero
- (to cater BOTH for no '0', '1', '8', or '9' AND for no '.')
µ - start a new monadic link (call that X)
_8 - subtract eight (vectorises across X)
¦ - sparse application...
1 - ...to: indices: one
H - ...do: halve (i.e. halve first ordinal)
%8 - modulo by eight (vectorises)
Ị - insignificant (abs(v)<=1?) (vectorises)
T - truthy indices
Ḣ - head
Ɗ - last three links as a monad (i.e. f(X)):
<48 - less than 48? (i.e. was it a '.' in S or the added 0?)
T - truthy indices
Ḣ - head
_ - subtract
¥ - last two links as a dyad
< 0 - less than zero? (1 if so 0 otherwise)
_ - subtract
ɓ - start a new dyadic chain (i.e. f(S,X))
V - evaluate S as Jelly code (i.e. get S as a float)
ær - round to the nearest multiple of 10^(-X)
$endgroup$
add a comment |
$begingroup$
Jelly, 30 29 bytes
-1 thanks to Erik the Outgolfer (use of dyadic quick ¥ from his answer)
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær
A monadic link accepting a list of characters which yields a float.
Try it online! Or see the test-suite.
How
First note that the input string is made exclusively from the characters 0123456789. which have ordinals [48,49,50,51,52,53,54,55,56,57,46], which have remainders when divided by eight of [0,1,2,3,4,5,6,7,0,1,6]. The only characters which are between -1 and 1 inclusive are 0, 1, 8, and 9.
Furthermore if we subtract eight from the ordinals ([40,41,42,43,44,45,46,47,48,49,38]) the same (fairly obviously) holds. If we halve these ([20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) the only characters which have remainders when divided by eight which are between -1 and 1 inclusive are 8 and 9.
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær - Link: list of characters, S
O - ordinal (vectorises across S)
;0 - concatenate a zero
- (to cater BOTH for no '0', '1', '8', or '9' AND for no '.')
µ - start a new monadic link (call that X)
_8 - subtract eight (vectorises across X)
¦ - sparse application...
1 - ...to: indices: one
H - ...do: halve (i.e. halve first ordinal)
%8 - modulo by eight (vectorises)
Ị - insignificant (abs(v)<=1?) (vectorises)
T - truthy indices
Ḣ - head
Ɗ - last three links as a monad (i.e. f(X)):
<48 - less than 48? (i.e. was it a '.' in S or the added 0?)
T - truthy indices
Ḣ - head
_ - subtract
¥ - last two links as a dyad
< 0 - less than zero? (1 if so 0 otherwise)
_ - subtract
ɓ - start a new dyadic chain (i.e. f(S,X))
V - evaluate S as Jelly code (i.e. get S as a float)
ær - round to the nearest multiple of 10^(-X)
$endgroup$
add a comment |
$begingroup$
Jelly, 30 29 bytes
-1 thanks to Erik the Outgolfer (use of dyadic quick ¥ from his answer)
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær
A monadic link accepting a list of characters which yields a float.
Try it online! Or see the test-suite.
How
First note that the input string is made exclusively from the characters 0123456789. which have ordinals [48,49,50,51,52,53,54,55,56,57,46], which have remainders when divided by eight of [0,1,2,3,4,5,6,7,0,1,6]. The only characters which are between -1 and 1 inclusive are 0, 1, 8, and 9.
Furthermore if we subtract eight from the ordinals ([40,41,42,43,44,45,46,47,48,49,38]) the same (fairly obviously) holds. If we halve these ([20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) the only characters which have remainders when divided by eight which are between -1 and 1 inclusive are 8 and 9.
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær - Link: list of characters, S
O - ordinal (vectorises across S)
;0 - concatenate a zero
- (to cater BOTH for no '0', '1', '8', or '9' AND for no '.')
µ - start a new monadic link (call that X)
_8 - subtract eight (vectorises across X)
¦ - sparse application...
1 - ...to: indices: one
H - ...do: halve (i.e. halve first ordinal)
%8 - modulo by eight (vectorises)
Ị - insignificant (abs(v)<=1?) (vectorises)
T - truthy indices
Ḣ - head
Ɗ - last three links as a monad (i.e. f(X)):
<48 - less than 48? (i.e. was it a '.' in S or the added 0?)
T - truthy indices
Ḣ - head
_ - subtract
¥ - last two links as a dyad
< 0 - less than zero? (1 if so 0 otherwise)
_ - subtract
ɓ - start a new dyadic chain (i.e. f(S,X))
V - evaluate S as Jelly code (i.e. get S as a float)
ær - round to the nearest multiple of 10^(-X)
$endgroup$
Jelly, 30 29 bytes
-1 thanks to Erik the Outgolfer (use of dyadic quick ¥ from his answer)
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær
A monadic link accepting a list of characters which yields a float.
Try it online! Or see the test-suite.
How
First note that the input string is made exclusively from the characters 0123456789. which have ordinals [48,49,50,51,52,53,54,55,56,57,46], which have remainders when divided by eight of [0,1,2,3,4,5,6,7,0,1,6]. The only characters which are between -1 and 1 inclusive are 0, 1, 8, and 9.
Furthermore if we subtract eight from the ordinals ([40,41,42,43,44,45,46,47,48,49,38]) the same (fairly obviously) holds. If we halve these ([20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) the only characters which have remainders when divided by eight which are between -1 and 1 inclusive are 8 and 9.
O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær - Link: list of characters, S
O - ordinal (vectorises across S)
;0 - concatenate a zero
- (to cater BOTH for no '0', '1', '8', or '9' AND for no '.')
µ - start a new monadic link (call that X)
_8 - subtract eight (vectorises across X)
¦ - sparse application...
1 - ...to: indices: one
H - ...do: halve (i.e. halve first ordinal)
%8 - modulo by eight (vectorises)
Ị - insignificant (abs(v)<=1?) (vectorises)
T - truthy indices
Ḣ - head
Ɗ - last three links as a monad (i.e. f(X)):
<48 - less than 48? (i.e. was it a '.' in S or the added 0?)
T - truthy indices
Ḣ - head
_ - subtract
¥ - last two links as a dyad
< 0 - less than zero? (1 if so 0 otherwise)
_ - subtract
ɓ - start a new dyadic chain (i.e. f(S,X))
V - evaluate S as Jelly code (i.e. get S as a float)
ær - round to the nearest multiple of 10^(-X)
edited Dec 8 '18 at 18:55
answered Dec 8 '18 at 18:17
Jonathan AllanJonathan Allan
51.2k534166
51.2k534166
add a comment |
add a comment |
$begingroup$
Retina 0.8.2, 75 bytes
^[89]
10
T`d`0`(?<=.)[01].*|(?<=8|9).*
T`89d`0d`..?[89]
(.|(..+?))0+$
$2
Try it online! Link includes test cases. Explanation:
^[89]
10
Handle the case of a leading 8 or 9.
T`d`0`(?<=.)[01].*|(?<=8|9).*
If there's a non-leading 0 or 1, then zero it and the rest of the string out. Also, if there's an 8 or 9, then leave it, but zero out the rest of the string. (But leave the decimal point unchanged in either case.)
T`89d`0d`..?[89]
If there's still an 8 or a 9 at this point, then zero it out, and increment the preceding digit (possibly before the decimal point).
(.|(..+?))0+$
$2
Delete trailing zeros if they are after a decimal point, but only delete the decimal point if there are no other digits in between.
$endgroup$
add a comment |
$begingroup$
Retina 0.8.2, 75 bytes
^[89]
10
T`d`0`(?<=.)[01].*|(?<=8|9).*
T`89d`0d`..?[89]
(.|(..+?))0+$
$2
Try it online! Link includes test cases. Explanation:
^[89]
10
Handle the case of a leading 8 or 9.
T`d`0`(?<=.)[01].*|(?<=8|9).*
If there's a non-leading 0 or 1, then zero it and the rest of the string out. Also, if there's an 8 or 9, then leave it, but zero out the rest of the string. (But leave the decimal point unchanged in either case.)
T`89d`0d`..?[89]
If there's still an 8 or a 9 at this point, then zero it out, and increment the preceding digit (possibly before the decimal point).
(.|(..+?))0+$
$2
Delete trailing zeros if they are after a decimal point, but only delete the decimal point if there are no other digits in between.
$endgroup$
add a comment |
$begingroup$
Retina 0.8.2, 75 bytes
^[89]
10
T`d`0`(?<=.)[01].*|(?<=8|9).*
T`89d`0d`..?[89]
(.|(..+?))0+$
$2
Try it online! Link includes test cases. Explanation:
^[89]
10
Handle the case of a leading 8 or 9.
T`d`0`(?<=.)[01].*|(?<=8|9).*
If there's a non-leading 0 or 1, then zero it and the rest of the string out. Also, if there's an 8 or 9, then leave it, but zero out the rest of the string. (But leave the decimal point unchanged in either case.)
T`89d`0d`..?[89]
If there's still an 8 or a 9 at this point, then zero it out, and increment the preceding digit (possibly before the decimal point).
(.|(..+?))0+$
$2
Delete trailing zeros if they are after a decimal point, but only delete the decimal point if there are no other digits in between.
$endgroup$
Retina 0.8.2, 75 bytes
^[89]
10
T`d`0`(?<=.)[01].*|(?<=8|9).*
T`89d`0d`..?[89]
(.|(..+?))0+$
$2
Try it online! Link includes test cases. Explanation:
^[89]
10
Handle the case of a leading 8 or 9.
T`d`0`(?<=.)[01].*|(?<=8|9).*
If there's a non-leading 0 or 1, then zero it and the rest of the string out. Also, if there's an 8 or 9, then leave it, but zero out the rest of the string. (But leave the decimal point unchanged in either case.)
T`89d`0d`..?[89]
If there's still an 8 or a 9 at this point, then zero it out, and increment the preceding digit (possibly before the decimal point).
(.|(..+?))0+$
$2
Delete trailing zeros if they are after a decimal point, but only delete the decimal point if there are no other digits in between.
answered Dec 8 '18 at 19:54
NeilNeil
79.9k744178
79.9k744178
add a comment |
add a comment |
$begingroup$
C (gcc), 111 102 bytes
g(_,i,j,k)char*_;{for(i=*_<56?*_++:48,j=3;j;j&=k%8>1|(i=*_++)/48*2)putchar(j&1?i+(k=_[*_<48])/56:48);}
Try it online!
//_: input, as string
//i: current digit, rounded if applicable
//j: tracks whether number is rounded, and whether or '.' has been encountered
//k: digit to test rounding (round if k is one of 0,1,8,9)
//'0'==48, '8'==56
g(_,i,j,k)char*_;{
for(i=*_<56?*_++:48,j=3; //special case: if first digit is 8 or 9, use a
//placeholder digit with value 0. initialize j.
j; //only stop execution when number is rounded and
//'.' or has been encountered.
j&=k%8>1|(i=*_++)/48*2) //check if execution should stop.
putchar(j&1?i+(k=_[*_<48])/56:48); //print '0' if rounding had already been done;
//otherwise, print digit. round up as needed.
}
$endgroup$
add a comment |
$begingroup$
C (gcc), 111 102 bytes
g(_,i,j,k)char*_;{for(i=*_<56?*_++:48,j=3;j;j&=k%8>1|(i=*_++)/48*2)putchar(j&1?i+(k=_[*_<48])/56:48);}
Try it online!
//_: input, as string
//i: current digit, rounded if applicable
//j: tracks whether number is rounded, and whether or '.' has been encountered
//k: digit to test rounding (round if k is one of 0,1,8,9)
//'0'==48, '8'==56
g(_,i,j,k)char*_;{
for(i=*_<56?*_++:48,j=3; //special case: if first digit is 8 or 9, use a
//placeholder digit with value 0. initialize j.
j; //only stop execution when number is rounded and
//'.' or has been encountered.
j&=k%8>1|(i=*_++)/48*2) //check if execution should stop.
putchar(j&1?i+(k=_[*_<48])/56:48); //print '0' if rounding had already been done;
//otherwise, print digit. round up as needed.
}
$endgroup$
add a comment |
$begingroup$
C (gcc), 111 102 bytes
g(_,i,j,k)char*_;{for(i=*_<56?*_++:48,j=3;j;j&=k%8>1|(i=*_++)/48*2)putchar(j&1?i+(k=_[*_<48])/56:48);}
Try it online!
//_: input, as string
//i: current digit, rounded if applicable
//j: tracks whether number is rounded, and whether or '.' has been encountered
//k: digit to test rounding (round if k is one of 0,1,8,9)
//'0'==48, '8'==56
g(_,i,j,k)char*_;{
for(i=*_<56?*_++:48,j=3; //special case: if first digit is 8 or 9, use a
//placeholder digit with value 0. initialize j.
j; //only stop execution when number is rounded and
//'.' or has been encountered.
j&=k%8>1|(i=*_++)/48*2) //check if execution should stop.
putchar(j&1?i+(k=_[*_<48])/56:48); //print '0' if rounding had already been done;
//otherwise, print digit. round up as needed.
}
$endgroup$
C (gcc), 111 102 bytes
g(_,i,j,k)char*_;{for(i=*_<56?*_++:48,j=3;j;j&=k%8>1|(i=*_++)/48*2)putchar(j&1?i+(k=_[*_<48])/56:48);}
Try it online!
//_: input, as string
//i: current digit, rounded if applicable
//j: tracks whether number is rounded, and whether or '.' has been encountered
//k: digit to test rounding (round if k is one of 0,1,8,9)
//'0'==48, '8'==56
g(_,i,j,k)char*_;{
for(i=*_<56?*_++:48,j=3; //special case: if first digit is 8 or 9, use a
//placeholder digit with value 0. initialize j.
j; //only stop execution when number is rounded and
//'.' or has been encountered.
j&=k%8>1|(i=*_++)/48*2) //check if execution should stop.
putchar(j&1?i+(k=_[*_<48])/56:48); //print '0' if rounding had already been done;
//otherwise, print digit. round up as needed.
}
edited Dec 28 '18 at 5:26
answered Dec 27 '18 at 7:58
attinatattinat
3305
3305
add a comment |
add a comment |
$begingroup$
C# (Visual C# Interactive Compiler), 280 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=decimal.Parse(c);Func<decimal>q=()=>(decimal)Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!
It can be shorter if I used doubles instead of decimals, but I used decimals to preserve accuracy, or else a number like 547.4726 would be 547.472595214844.
C# (Visual C# Interactive Compiler), 268 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=float.Parse(c);Func<double>q=()=>Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!(Less accurate version)
$endgroup$
add a comment |
$begingroup$
C# (Visual C# Interactive Compiler), 280 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=decimal.Parse(c);Func<decimal>q=()=>(decimal)Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!
It can be shorter if I used doubles instead of decimals, but I used decimals to preserve accuracy, or else a number like 547.4726 would be 547.472595214844.
C# (Visual C# Interactive Compiler), 268 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=float.Parse(c);Func<double>q=()=>Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!(Less accurate version)
$endgroup$
add a comment |
$begingroup$
C# (Visual C# Interactive Compiler), 280 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=decimal.Parse(c);Func<decimal>q=()=>(decimal)Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!
It can be shorter if I used doubles instead of decimals, but I used decimals to preserve accuracy, or else a number like 547.4726 would be 547.472595214844.
C# (Visual C# Interactive Compiler), 268 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=float.Parse(c);Func<double>q=()=>Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!(Less accurate version)
$endgroup$
C# (Visual C# Interactive Compiler), 280 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=decimal.Parse(c);Func<decimal>q=()=>(decimal)Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!
It can be shorter if I used doubles instead of decimals, but I used decimals to preserve accuracy, or else a number like 547.4726 would be 547.472595214844.
C# (Visual C# Interactive Compiler), 268 bytes
c=>{int d=c.IndexOf('.');int t=c.IndexOfAny(new char{'8','9','0','1'},1);var m=c[0]=='8'||c[0]=='9'?1>0:0>1;var z=float.Parse(c);Func<double>q=()=>Math.Pow(10,m?d<0?c.Length:d:d<0?c.Length-t:d>t?d-t:d-t+1);return m?Math.Round(z/q())*q():t<0?z:Math.Round(z/q())*q();}
Try it online!(Less accurate version)
edited Dec 11 '18 at 21:24
answered Dec 11 '18 at 4:01
Embodiment of IgnoranceEmbodiment of Ignorance
691115
691115
add a comment |
add a comment |
If this is an answer to a challenge…
…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.
…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.
More generally…
…Please make sure to answer the question and provide sufficient detail.
…Avoid asking for help, clarification or responding to other answers (use comments instead).
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f177203%2fsatisfying-rounding%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Sandbox
$endgroup$
– Quintec
Dec 8 '18 at 15:11
$begingroup$
Are strings such as
036.40000considered a valid output?$endgroup$
– Arnauld
Dec 8 '18 at 16:08
1
$begingroup$
Can we assume that a
.0part will be given for integers? Also,0isn't positive.$endgroup$
– Erik the Outgolfer
Dec 8 '18 at 16:08
$begingroup$
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
$endgroup$
– Quintec
Dec 8 '18 at 17:03
1
$begingroup$
So
19rounds to20but0.19rounds to0? Why?$endgroup$
– Neil
Dec 8 '18 at 19:38