満足のいく丸め


16

満足のいく丸め

あなたは理科の授業にいるときを知っており、2 sigのイチジクに丸めることを求めましたが、あなたの答えは5.2501...?に丸める必要がありますが5.3、それはとても不満です!に四捨五入する5.3ことにより、0.05(四捨五入する場所の値)に比べて0.05だけ大きくなります!だから私は満足のいく方法でラウンドを助けてください。

満足のいく方法で丸めるには、出くわす最初の桁で丸める必要があります。これは、誤差が比較的小さく、丸め時に可能な最大誤差の半分未満です。基本的に、0、1、8、または9に遭遇するたびに丸める必要があります。それが起こらない場合は、入力をそのまま返します。先頭のゼロまたは1を丸めないでください-それは単に満足感を感じません。

入力

非負の10進数を表す文字列または浮動小数点値。

出力

文字列または浮動小数点形式のいずれかで、十分に丸められた同じ10進数。

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有効な出力とみなされるような文字列はありますか?
アーナルド

1
.0整数の部分が与えられると仮定できますか?また、0肯定的ではありません。
エリックアウトゴルファー

@EriktheOutgolferいいえ、できません-おかげで、非負に変更されました。
Quintec

1
だから19丸めますが200.19丸め0ますか?どうして?
ニール

回答:


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)

オンラインでお試しください!

どうやって?

最初に先頭のを入力文字列の先頭に追加します。これにより、可能な先頭のまたは前に、すぐに丸めをトリガーする必要がある数字があることが保証されます。089

フラグjは、満足のいく丸めを行うことができる数字を探している限り1設定され、その後0に設定されます

歩く文字列に先頭の0が追加されたが、sは変更されないままであるため、dには現在の文字が含まれ、s[i]次の文字を指します。

次のコードを使用して、nの次の数字をロードし、可能な小数点区切り文字をスキップします。

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

JavaScriptでは文字列は不変ですが、数値が含まれている場合、s [ i ]が実際にインクリメントされていなくても、式++s[i]s[i]+1を返します。したがって、式は、すべての数字(0を含む)についてはf a l s e0に強制)に評価され、小数点区切り文字にはt r u e1に強制)に評価されます。s[i]!++s[i]false00true1"."

丸めが発生した場合、我々は得d + --j次の桁場合nである0または1(それは元の入力の先頭の数字はない)、およびd + j--場合nである8又は9。したがって、jに設定されている0の両方の場合に我々は追加0d最初のケースでは(切り捨て)と1(切り上げ)は、第2の場合には。


1
そして、ピンボール/ゴムボールは溝に落ちます!:)
Quintec

2

ルビー79 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/non-starting 0-1またはanyの8-9どちらか早い方の位置を決定します。
  • (...)-i この差は、保持する小数点以下の桁数になり、ドットの左側を丸める場合は負になります。
  • n.to_f.round ... フロートに変換し、丸めを行います。

1

ゼリー、34バイト

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

オンラインでお試しください!

-1 ジョナサンアランに感謝します。


なんでŒVVうまくいくと思います。
ジョナサンアラン

@JonathanAllan いいえ (基本的に銀行家の丸めの癖)
エリック・ザ・アウトゴルファー

ああ、それは入力に作用していないのですか?_>¥0ɓVær私のように試してみてください(ダイアディックの使用方法を逃したので、ありがとうございます!)
ジョナサンアラン

@JonathanAllan Ah、チェーンの賢い使い方、ありがとう。
エリックアウトゴルファー

1

ゼリー 30  29 バイト

-1アウトゴルファーのエリックに感謝(¥回答からすぐにダイアディックを使用)

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

floatを生成する文字のリストを受け入れるモナドリンク。

オンラインでお試しください!または、テストスイートを参照してください。

どうやって

入力文字列は、文字のみから作られていることをまずノート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で割ったときの余りを持っている唯一の文字-11包括的にある89

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

Retina 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).*

先頭に0ないまたはがある1場合、ゼロと残りの文字列をゼロにします。また、8またはがある場合9はそのままにして、残りの文字列をゼロにします。(ただし、どちらの場合も小数点は変更しないでください。)

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

この時点でまだ8またはが残っている場合は9、それをゼロにし、前の桁を(おそらく小数点の前に)増やします。

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

小数点の後に続くゼロは削除しますが、間に他の数字がない場合にのみ小数点を削除します。


1

C(gcc)111 102バイト

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#Interactive Compiler)、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#Interactive Compiler)、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();}

オンラインで試してみてください!(正確度の低いバージョン)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.