令人满意的舍入


16

令人满意的舍入

您知道在上科学课时需要四舍五入到2个无花果,但是您的答案是5.2501...?您应该四舍五入到5.3,但这太不令人满意了!通过四舍五入到5.3,您将得到0.05的整数,与0.1(四舍五入到的位值)相比,这是一个很大的数目!因此,请以令人满意的方式帮助我。

要以令人满意的方式进行舍入,必须在遇到的第一个数字处舍入会产生相对较小的误差-小于舍入时可能出现的最大误差的一半。基本上,您需要在遇到0、1、8或9时四舍五入。如果永远不会发生,请按原样返回输入。不要四舍五入到前导零或一个-只是让人感到不满意。

输入值

表示非负十进制数字的字符串或浮点值。

输出量

可以将十进制数字以字符串或浮点格式令人满意地舍入。

例子

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

这是一个挑战,所以最短的代码胜出!



是否将诸如这样的字符串036.40000视为有效输出?
Arnauld

1
我们.0是否可以假定整数部分?此外,0也不是积极的。
Erik the Outgolfer

@EriktheOutgolfer不,您可能不会-还要感谢,已更改为非负数。
Quintec '18

1
如此19舍入20而是0.19舍入为0?为什么?
尼尔,

Answers:


2

JavaScript(ES6), 100 99 98  78字节

将输入作为字符串。返回一个浮点数。

s=>+(0+s).replace(/\d/g,(d,i)=>j&&+d+((n=s[i+!++s[i]])<2&&i?--j:n>7&&j--),j=1)

在线尝试!

怎么样?

我们首先在输入字符串前添加前导0,以便确保在可能的前导89之前有一个数字,该数字必须立即触发四舍五入。

只要我们在寻找可以进行令人满意的舍入的数字,就将标志Ĵ设置为1个,然后再将其设置为0

因为在我们要遍历的字符串中添加了前导0,但s保持不变,所以d包含当前字符,而s[一世]指向下一个字符。

我们使用以下代码加载ñ的下一位,跳过可能的小数点分隔符:

n = s[i + !++s[i]]

虽然字符串在JavaScript中是不可变的,所述表达++s[i]会返回s[一世]+1个如果它包含一个数值,即使s[一世]实际上不递增。因此,表达式!++s[i]被评估以F一种sË(强制为0)的所有位(包括0),并Ť[RüË(强制为1个),用于小数分隔"."

当舍入发生时,我们得到d + --j如果下一个数字ñ01个(和它不是原始输入的前导数位)和d + j--如果ñ89。因此,在两种情况下,Ĵ都设置为0,但在第一种情况(向下舍入)中我们将d添加0,在第二种情况(向上舍入)中将d添加1个


1
弹球/橡胶球掉进沟里!:)
Quintec '18

2

Ruby79 77 69 67 65字节

->n,z=n+".0"{z[i=z=~/\./]='';n.to_f.round (z=~/(?!^)[01]|8|9/)-i}

在线尝试!

说明

  • ->n 将输入作为字符串
  • z=n+".0"创建一个z保证包含点和相关数字的临时字符串。
  • i=z=~/\./确定小数点在中的位置z并分配给i
  • z[i]='' 放下该点,以免其进一步干扰。
  • z=~/(?!^)[01]|8|9/确定不启动0-1或任何位置8-9,以先到者为准。
  • (...)-i 此差异将为保留的小数位数,如果我们将圆点左舍入,则为负数。
  • n.to_f.round ... 转换为float并进行舍入。

1

果冻,34个字节

;”.ḟ$µ»"”2e€⁽¡XṾ¤;1i1_i”.$_>¥0ɓVær

在线尝试!

-1感谢乔纳森·艾伦


为什么ŒV呢 我认为V也可以。
乔纳森·艾伦

@乔纳森·艾伦·诺普(JonathanAllan Nope)。(基本上是银行家的四舍五入的怪癖)
Egg the Outgolfer

哦,因为它没有作用于输入?_>¥0ɓVær像我一样尝试(我错过了快速使用二进位的功能,所以也谢谢!)
Jonathan Allan '18

@JonathanAllan啊,巧妙地使用链条,谢谢。
暴民埃里克(Erik the Outgolfer)'18年

1

果冻 30  29 字节

-1感谢Outgolfer的Erik(快速¥使用他的答案中的二进位符号)

O;0µ_8H1¦%8ỊTḢ_<48TḢƊ_>¥0ɓVær

单子链接接受一个产生浮点数的字符列表。

在线尝试!或查看测试套件

怎么样

首先请注意,输入字符串仅由0123456789.具有序数的字符组成,这些序[48,49,50,51,52,53,54,55,56,57,46]数在被8的整数除时具有余数[0,1,2,3,4,5,6,7,0,1,6]。它们之间唯一的字符-11包容性的是018,和9

此外,如果我们从序数([40,41,42,43,44,45,46,47,48,49,38])中减去8,则同样(显然)成立。如果将这些([20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19])减半,则只有除以8的介于-1和之间的字符将189

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)

1

视网膜0.8.2,75字节

^[89]
10
T`d`0`(?<=.)[01].*|(?<=8|9).*
T`89d`0d`.\.?[89]
(\.|(\..+?))0+$
$2

在线尝试!链接包括测试用例。说明:

^[89]
10

处理引线8或引线的情况9

T`d`0`(?<=.)[01].*|(?<=8|9).*

如果存在非前导01,则将其归零,然后将字符串的其余部分排除。另外,如果存在89,则将其保留,但将其余字符串置零。(但无论哪种情况,小数点都保持不变。)

T`89d`0d`.\.?[89]

如果此时仍存在a 8或a 9,则将其清零,并递增前一位(可能在小数点之前)。

(\.|(\..+?))0+$
$2

如果尾随零在小数点后,则删除尾随零,而仅当尾随零之间没有其他数字时,才删除小数点。


1

C(gcc)111字节

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);}

在线尝试!

//_: input, as string
//i: current digit, rounded if applicable
//j: tracks whether number is rounded, and whether \0 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 \0 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.
}

0

C#(Visual C#交互式编译器),280字节

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();}

在线尝试!

如果我使用双精度代替小数,则可能会更短一些,但是为了保持精度,我使用了小数,否则,如547.4726的数字将为547.472595214844。

C#(Visual C#交互式编译器),268字节

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();}

在线尝试!(精确度较低的版本)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.