Làm tròn thỏa mãn


16

Làm tròn thỏa mãn

Bạn biết khi bạn học lớp khoa học và được yêu cầu làm tròn đến 2 quả sung, nhưng câu trả lời của bạn là 5.2501...? Bạn nên làm tròn 5.3, nhưng điều đó thật không thỏa mãn! Bằng cách làm tròn đến 5.3, bạn giảm toàn bộ 0,05, một lượng lớn so với 0,1 (giá trị địa điểm bạn đang làm tròn)! Vì vậy, giúp tôi làm tròn một cách thỏa mãn.

Để làm tròn theo cách thỏa mãn, bạn phải làm tròn ở chữ số đầu tiên bạn gặp phải tạo ra một lỗi tương đối nhỏ - ít hơn một nửa lỗi tối đa có thể xảy ra khi làm tròn. Về cơ bản, bạn cần làm tròn bất cứ khi nào bạn gặp 0, 1, 8 hoặc 9. Nếu điều đó không bao giờ xảy ra, hãy trả lại đầu vào như hiện tại. Đừng làm tròn số 0 hoặc số hàng đầu - điều đó không cảm thấy thỏa mãn.

Đầu vào

Một chuỗi hoặc giá trị float đại diện cho một số thập phân không âm.

Đầu ra

Số thập phân giống nhau được làm tròn thỏa đáng, ở dạng chuỗi hoặc dấu phẩy.

Ví dụ

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

Đây là một thử thách , vì vậy mã ngắn nhất sẽ thắng!



Là các chuỗi như 036.40000được coi là một đầu ra hợp lệ?
Arnauld

1
Chúng ta có thể giả định rằng một .0phần sẽ được cung cấp cho số nguyên? Ngoài ra, 0không tích cực.
Erik the Outgolfer 8/12/18

@EriktheOutgolfer Không, bạn có thể không - cũng cảm ơn, đã đổi thành không âm.
Quintec

1
Vậy 19vòng đến 20nhưng 0.19vòng đến 0? Tại sao?
Neil

Câu trả lời:


2

JavaScript (ES6),  100 99 98  78 byte

Đưa đầu vào dưới dạng một chuỗi. Trả lại một float.

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

Hãy thử trực tuyến!

Làm sao?

Trước tiên, chúng tôi trả trước 0 cho chuỗi đầu vào, để chúng tôi được đảm bảo có một chữ số trước 8 hoặc 9 có thể dẫn đầu , điều đó phải kích hoạt làm tròn số ngay lập tức.

Cờ j được đặt thành 1 miễn là chúng ta đang tìm kiếm một chữ số mà chúng ta có thể thực hiện làm tròn thỏa mãn và đặt thành 0 sau đó.

Bởi vì một số 0 đứng đầu đã được thêm vào chuỗi mà chúng ta đang đi qua nhưng s không thay đổi, d chứa ký tự hiện tại và s[i] đang trỏ đến ký tự tiếp theo .

Chúng tôi sử dụng mã sau đây để tải chữ số tiếp theo trong n , bỏ qua dấu phân cách thập phân có thể:

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

Mặc dù các chuỗi là bất biến trong JavaScript, biểu thức ++s[i]sẽ trả về s[i]+1 nếu nó chứa giá trị số, mặc dù s[i] không thực sự tăng. Do đó, biểu thức !++s[i]được ước tính là false (bị ép thành 0 ) cho tất cả các chữ số (bao gồm 0 ) và true (bị ép thành 1 ) cho dấu tách thập phân ".".

Khi làm tròn xảy ra, chúng tôi mang lại d + --jnếu chữ số n tiếp theo là 0 hoặc 1 (và đó không phải là chữ số hàng đầu của đầu vào ban đầu) và d + j--nếu n89j00d1


1
Và quả bóng pinball / cao su rơi xuống một con mương! :)
Quintec

2

Ruby , 79 77 69 67 65 byte

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

Hãy thử trực tuyến!

Giải trình

  • ->n Lấy đầu vào dưới dạng chuỗi
  • z=n+".0"Tạo một chuỗi tạm thời zđược đảm bảo để chứa một dấu chấm và một chữ số có liên quan.
  • i=z=~/\./Xác định vị trí của dấu chấm thập phân trong zvà gán cho i.
  • z[i]='' Thả dấu chấm để nó không bị cản trở.
  • z=~/(?!^)[01]|8|9/Xác định vị trí không bắt đầu 0-1hoặc bất kỳ 8-9, tùy theo điều kiện nào đến trước.
  • (...)-i Sự khác biệt này sẽ là số vị trí thập phân cần giữ, âm nếu chúng ta làm tròn trái của dấu chấm.
  • n.to_f.round ... Chuyển đổi để nổi và làm tròn.

1

Thạch , 34 byte

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

Hãy thử trực tuyến!

-1 cảm ơn Jonathan Allan .


Tại sao ŒV? Tôi nghĩ rằng Vsẽ làm việc quá.
Jonathan Allan

@Jonathan ALLan Không. (về cơ bản của ngân hàng làm tròn quirks)
Erik các Outgolfer

Oh, bởi vì nó không hoạt động trên đầu vào? Hãy thử _>¥0ɓVærnhư của tôi (Tôi đã bỏ lỡ việc sử dụng thuốc nhuộm nhanh chóng vì vậy cũng cảm ơn!)
Jonathan Allan

@Jonathan ALLan Ah, sử dụng chuỗi thông minh, cảm ơn.
Erik các Outgolfer

1

Thạch ,  30  29 byte

-1 cảm ơn Erik the Outgolfer (sử dụng dyadic nhanh ¥từ câu trả lời của anh ấy)

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

Một liên kết đơn âm chấp nhận một danh sách các ký tự mang lại sự nổi.

Hãy thử trực tuyến! Hoặc xem bộ thử nghiệm .

Làm sao

Đầu tiên lưu ý rằng chuỗi đầu vào được tạo riêng từ các ký tự 0123456789.có số thứ tự [48,49,50,51,52,53,54,55,56,57,46], phần còn lại khi chia cho tám [0,1,2,3,4,5,6,7,0,1,6]. Các nhân vật duy nhất là giữa -11toàn diện là 0, 1, 8, và9 .

Hơn nữa, nếu chúng ta trừ tám từ các số thứ tự ( [40,41,42,43,44,45,46,47,48,49,38]) giống nhau (khá rõ ràng). Nếu chúng ta giảm một nửa ( [20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) các ký tự duy nhất còn lại khi chia cho tám ký tự nằm giữa -11bao gồm là 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

Võng mạc 0.8.2 , 75 byte

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

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm. Giải trình:

^[89]
10

Xử lý các trường hợp hàng đầu 8hoặc 9.

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

Nếu không có đầu 0hoặc 1, thì không và phần còn lại của chuỗi ra. Ngoài ra, nếu có 8hoặc 9, sau đó bỏ nó, nhưng không có phần còn lại của chuỗi. (Nhưng không thay đổi dấu thập phân trong cả hai trường hợp.)

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

Nếu vẫn còn một 8hoặc một 9điểm tại thời điểm này, thì hãy xóa nó đi và tăng chữ số trước đó (có thể trước dấu thập phân).

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

Xóa các số 0 ở cuối nếu chúng nằm sau dấu thập phân, nhưng chỉ xóa dấu thập phân nếu không có chữ số nào khác ở giữa.


1

C (gcc) , 111 102 byte

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

Hãy thử trực tuyến!

//_: 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 # (Trình biên dịch tương tác Visual C #) , 280 byte

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

Hãy thử trực tuyến!

Nó có thể ngắn hơn nếu tôi sử dụng gấp đôi thay vì số thập phân, nhưng tôi đã sử dụng số thập phân để bảo toàn độ chính xác, nếu không, một số như 547.4726 sẽ là 547.472595214844.

C # (Trình biên dịch tương tác Visual C #) , 268 byte

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

Dùng thử trực tuyến! (Phiên bản ít chính xác hơn)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.