Tatmin Edici Yuvarlama


16

Tatmin Edici Yuvarlama

Fen dersinde olduğunuzu biliyorsunuz ve 2 sig incir yuvarlamak istediniz, ama cevabınız 5.2501...? Yuvarlanmalısın 5.3, ama bu çok tatmin edici değil! Yuvarlayarak 5.3, 0.1'e (yuvarladığınız yer değeri) kıyasla büyük bir miktar olan 0,05'lik bir oranın dışındasınız! Bu yüzden tatmin edici bir şekilde dönmeme yardım et.

Tatmin edici bir şekilde yuvarlamak için, karşılaştığınız ilk haneyi göreceli olarak küçük bir hata oluşturan yuvarlama yapmanız gerekir - yuvarlama sırasında mümkün olan maksimum hatanın yarısından daha az. Temel olarak, 0, 1, 8 veya 9 ile karşılaştığınızda yuvarlamanız gerekir. Bu asla olmazsa girişi olduğu gibi döndürün. Baştaki sıfırları veya sıfırları yuvarlamayın - bu tatmin edici hissetmez.

Giriş

Negatif olmayan bir ondalık sayı gösteren bir dize veya kayan değer.

Çıktı

Aynı ondalık sayı dize veya kayan noktalı biçimde tatmin edici şekilde yuvarlanır.

Örnekler

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

Bu bir mücadelesi, bu yüzden en kısa kod kazanır!



Gibi dizeler 036.40000geçerli çıktı olarak kabul edilir mi?
Arnauld

1
.0Tamsayılar için bir bölüm verileceğini varsayabilir miyiz ? Ayrıca, 0olumlu değil.
Outgolfer Erik

@EriktheOutgolfer Hayır, yapamazsınız - ayrıca teşekkürler, negatif olmayan olarak değiştirildi.
Quintec

1
Yani 19yuvarlanıyor 20ama 0.19yuvarlanıyor 0? Neden?
Neil

Yanıtlar:


2

JavaScript (ES6),  100 99 98  78 bayt

Girişi dize olarak alır. Bir şamandıra döndürür.

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

Çevrimiçi deneyin!

Nasıl?

Öncelikle giriş dizesine 0 başını ekleriz , böylece olası bir 8 veya 9 başından önce yuvarlamayı hemen tetiklemesi gereken bir rakamımız olması garanti edilir .

j bayrağı , tatmin edici bir yuvarlama yapabileceğimiz bir rakam aradığımız sürece 1 ayarlanır ve daha sonra 0 ayarlanır .

Yürüdüğümüz dizeye baştaki 0 eklendiği, ancak s değişmediği için, d geçerli karakteri içerir ve s[ben] sonraki karakteri işaret eder .

Bir sonraki basamağı n yüklemek ve olası bir ondalık ayırıcıyı atlamak için aşağıdaki kodu kullanırız :

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

Dizeler JavaScript'te değiştirilemese de, s [ i ] aslında artırılmamış olsa bile, ifade sayısal bir değer içeriyorsa s [ i ] + 1 değerini ++s[i]döndürür . Bu nedenle, sentezleme için değerlendirilir f bir L s e (zorlanır 0 (dahil olmak üzere tüm basamak için) 0 ) ve t r u e (zorlanır 1 ) için ondalık ayırıcı .s[ben]+1s[ben]!++s[i]fbirlse00true1"."

d + --jn01d + j--n89j00d1


1
Ve langırt / lastik top bir hendekte düşüyor! :)
Quintec

2

Yakut , 79 77 69 67 65 bayt

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

Çevrimiçi deneyin!

açıklama

  • ->n Girdiyi dize olarak alma
  • z=n+".0"zNokta ve ilgili bir rakam içermesi garanti edilen geçici bir dize oluşturun .
  • i=z=~/\./Ondalık noktanın konumunu belirleyin zve atayın i.
  • z[i]='' Daha fazla ilerlememesi için noktayı bırakın.
  • z=~/(?!^)[01]|8|9/Hangisi önce gelirse, başlamayan 0-1veya herhangi birinin konumunu belirleyin 8-9.
  • (...)-i Bu fark, saklanacak ondalık basamak sayısı, noktanın soluna yuvarlanırsak negatif olacaktır.
  • n.to_f.round ... Şamandıraya dönüştürün ve yuvarlamayı yapın.

1

Jöle , 34 bayt

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

Çevrimiçi deneyin!

-1 Jonathan Allan sayesinde .


Neden ŒV? Bence Vde işe yarayacak.
Jonathan Allan

@JonathanAllan Nope. (temelde bankacının yuvarlama tuhaflıkları)
Outgolfer Erik

Oh, çünkü bu girdi üzerinde etkili değil mi? _>¥0ɓVærBenimki gibi dene (Ben iki hızlı kullanımı kaçırdım bu yüzden çok teşekkürler!)
Jonathan Allan

@JonathanAllan Ah, akıllı zincir kullanımı, teşekkürler.
Outgolfer Erik

1

Jöle ,  30  29 bayt

-1 Outgolfer Erik sayesinde (cevabından ikili hızlı kullanımı ¥)

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

Bir kayan nokta veren karakterlerin listesini kabul eden monadik bir bağlantı.

Çevrimiçi deneyin! Veya test takımına bakın .

Nasıl

İlk olarak, giriş dizesinin yalnızca 0123456789.sıralarına [48,49,50,51,52,53,54,55,56,57,46]sahip, sekize bölündüğünde kalan karakterlerden oluştuğunu unutmayın [0,1,2,3,4,5,6,7,0,1,6]. Arasında yalnızca karakterler -1ve 1kapsayıcı olan 0, 1, 8ve 9.

Dahası, ordinallerden ( [40,41,42,43,44,45,46,47,48,49,38]) sekiz çıkarırsak , aynı (oldukça açık bir şekilde) geçerlidir. Bunları yarıya indirirsek ( [20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]), aralarında -1ve 1kapsayıcı olan sekize bölündüğünde kalan karakterler 8ve olur 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)

1

Retina 0.8.2 , 75 bayt

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

Çevrimiçi deneyin! Bağlantı, test senaryolarını içerir. Açıklama:

^[89]
10

Önde gelen bir 8veya 9.

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

Lider olmayan 0veya varsa 1, sıfırlayın ve dizenin geri kalanını sıfırlayın. Ayrıca, bir 8veya varsa 9, bırakın, ancak dizenin geri kalanını sıfırlayın. (Ancak her iki durumda da ondalık noktasını değiştirmeden bırakın.)

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

Bu noktada hala bir 8veya a varsa 9, sıfırlayın ve önceki basamağı artırın (muhtemelen ondalık noktasından önce).

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

Ondalık noktadan sonra olan sondaki sıfırları silin, ancak ondalık basamakları yalnızca aralarında başka basamak yoksa silin.


1

C (GCC) , 111 102 bayt

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

Çevrimiçi deneyin!

//_: 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 # Etkileşimli Derleyici) , 280 bayt

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

Çevrimiçi deneyin!

Ondalık yerine çiftler kullanırsam daha kısa olabilir, ancak doğruluğu korumak için ondalık sayılar kullandım, yoksa 547.4726 gibi bir sayı 547.472595214844 olur.

C # (Visual C # Etkileşimli Derleyici) , 268 bayt

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

Çevrimiçi deneyin! (Daha az doğru sürüm)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.