Satisfying Rounding
up vote
15
down vote
favorite
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
|
show 5 more comments
up vote
15
down vote
favorite
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
Sandbox
– Quintec
2 days ago
Are strings such as036.40000considered a valid output?
– Arnauld
2 days ago
1
Can we assume that a.0part will be given for integers? Also,0isn't positive.
– Erik the Outgolfer
2 days ago
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
– Quintec
2 days ago
@Arnauld No leading nor trailing zeroes, since that kind of defeats the purpose of rounding.
– Quintec
2 days ago
|
show 5 more comments
up vote
15
down vote
favorite
up vote
15
down vote
favorite
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
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 yesterday
asked 2 days ago
Quintec
1,3001519
1,3001519
Sandbox
– Quintec
2 days ago
Are strings such as036.40000considered a valid output?
– Arnauld
2 days ago
1
Can we assume that a.0part will be given for integers? Also,0isn't positive.
– Erik the Outgolfer
2 days ago
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
– Quintec
2 days ago
@Arnauld No leading nor trailing zeroes, since that kind of defeats the purpose of rounding.
– Quintec
2 days ago
|
show 5 more comments
Sandbox
– Quintec
2 days ago
Are strings such as036.40000considered a valid output?
– Arnauld
2 days ago
1
Can we assume that a.0part will be given for integers? Also,0isn't positive.
– Erik the Outgolfer
2 days ago
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
– Quintec
2 days ago
@Arnauld No leading nor trailing zeroes, since that kind of defeats the purpose of rounding.
– Quintec
2 days ago
Sandbox
– Quintec
2 days ago
Sandbox
– Quintec
2 days ago
Are strings such as
036.40000 considered a valid output?– Arnauld
2 days ago
Are strings such as
036.40000 considered a valid output?– Arnauld
2 days ago
1
1
Can we assume that a
.0 part will be given for integers? Also, 0 isn't positive.– Erik the Outgolfer
2 days ago
Can we assume that a
.0 part will be given for integers? Also, 0 isn't positive.– Erik the Outgolfer
2 days ago
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
– Quintec
2 days ago
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
– Quintec
2 days ago
@Arnauld No leading nor trailing zeroes, since that kind of defeats the purpose of rounding.
– Quintec
2 days ago
@Arnauld No leading nor trailing zeroes, since that kind of defeats the purpose of rounding.
– Quintec
2 days ago
|
show 5 more comments
5 Answers
5
active
oldest
votes
up vote
2
down vote
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).
1
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
add a comment |
up vote
2
down vote
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.
add a comment |
up vote
1
down vote
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
WhyŒV? I thinkVwill work too.
– Jonathan Allan
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
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!)
– Jonathan Allan
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
add a comment |
up vote
1
down vote
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)
add a comment |
up vote
1
down vote
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.
add a comment |
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
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).
1
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
add a comment |
up vote
2
down vote
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).
1
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
add a comment |
up vote
2
down vote
up vote
2
down vote
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).
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 yesterday
answered 2 days ago
Arnauld
70.9k688298
70.9k688298
1
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
add a comment |
1
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
1
1
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
And the pinball/rubber ball falls into a ditch! :)
– Quintec
2 days ago
add a comment |
up vote
2
down vote
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.
add a comment |
up vote
2
down vote
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.
add a comment |
up vote
2
down vote
up vote
2
down vote
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.
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 yesterday
answered 2 days ago
Kirill L.
3,4051118
3,4051118
add a comment |
add a comment |
up vote
1
down vote
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
WhyŒV? I thinkVwill work too.
– Jonathan Allan
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
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!)
– Jonathan Allan
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
add a comment |
up vote
1
down vote
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
WhyŒV? I thinkVwill work too.
– Jonathan Allan
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
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!)
– Jonathan Allan
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
add a comment |
up vote
1
down vote
up vote
1
down vote
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
Jelly, 34 bytes
;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær
Try it online!
-1 thanks to Jonathan Allan.
edited 2 days ago
answered 2 days ago
Erik the Outgolfer
31k429102
31k429102
WhyŒV? I thinkVwill work too.
– Jonathan Allan
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
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!)
– Jonathan Allan
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
add a comment |
WhyŒV? I thinkVwill work too.
– Jonathan Allan
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
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!)
– Jonathan Allan
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
Why
ŒV? I think V will work too.– Jonathan Allan
2 days ago
Why
ŒV? I think V will work too.– Jonathan Allan
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
@JonathanAllan Nope. (basically banker's rounding quirks)
– Erik the Outgolfer
2 days ago
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!)– Jonathan Allan
2 days ago
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!)– Jonathan Allan
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
@JonathanAllan Ah, clever usage of chains, thanks.
– Erik the Outgolfer
2 days ago
add a comment |
up vote
1
down vote
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)
add a comment |
up vote
1
down vote
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)
add a comment |
up vote
1
down vote
up vote
1
down vote
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)
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 2 days ago
answered 2 days ago
Jonathan Allan
50.5k534165
50.5k534165
add a comment |
add a comment |
up vote
1
down vote
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.
add a comment |
up vote
1
down vote
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.
add a comment |
up vote
1
down vote
up vote
1
down vote
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.
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 2 days ago
Neil
78.6k744175
78.6k744175
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).
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Sandbox
– Quintec
2 days ago
Are strings such as
036.40000considered a valid output?– Arnauld
2 days ago
1
Can we assume that a
.0part will be given for integers? Also,0isn't positive.– Erik the Outgolfer
2 days ago
@EriktheOutgolfer No, you may not - also thanks, changed to nonnegative.
– Quintec
2 days ago
@Arnauld No leading nor trailing zeroes, since that kind of defeats the purpose of rounding.
– Quintec
2 days ago