การปัดเศษที่น่าพอใจ


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

1
ดังนั้น19รอบ20แต่0.19รอบ0? ทำไม?
Neil

คำตอบ:


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นำหน้าไปยังสตริงอินพุตเพื่อให้เรารับประกันว่าจะมีตัวเลขก่อนนำหน้า8หรือ9 ที่เป็นไปได้9ที่ที่จะต้องเรียกการปัดเศษทันที

ธงjตั้งค่าเป็น1ตราบเท่าที่เรากำลังมองหาตัวเลขที่เราสามารถทำการปัดเศษที่น่าพอใจและตั้งค่าเป็น0หลังจากนั้น

0sds[i]อักขระ

n

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

++s[i]s[i]+1s[i]!++s[i]false00true1"."

d + --jn01d + j--n89j00d1


1
และลูกบอลพินบอล / ยางตกลงไปในคู! :)
Quintec

2

Ruby , 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=~/\./กำหนดตำแหน่งของทศนิยมจุดในและกำหนดที่จะzi
  • z[i]='' วางจุดเพื่อไม่ให้มันไปขวางทางต่อไป
  • z=~/(?!^)[01]|8|9/กำหนดตำแหน่งของการไม่เริ่ม0-1หรือ8-9สิ่งใดก็ตามที่มาก่อน
  • (...)-i ความแตกต่างนี้จะเป็นจำนวนตำแหน่งทศนิยมที่จะเก็บไว้เป็นลบถ้าเราจะปัดเศษทางซ้ายของจุด
  • n.to_f.round ... แปลงเป็นการลอยและทำการปัดเศษ

1

Jelly, 34 bytes

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

Try it online!

-1 thanks to Jonathan Allan.


Why ŒV? I think V will work too.
Jonathan Allan

@JonathanAllan Nope (
นิสัย

โอ้เพราะมันไม่ได้ทำหน้าที่อินพุต? ลอง_>¥0ɓVærเหมือนของฉันคือ (ฉันพลาดการใช้ dyadic อย่างรวดเร็วขอบคุณมาก!)
Jonathan Allan

@JonathanAllan Ah, การใช้โซ่ที่ชาญฉลาดขอบคุณ
Erik the Outgolfer

1

เจลลี่ ,  30  29 ไบต์

-1 ต้องขอบคุณ Erik the Outgolfer (ใช้ dyadic อย่างรวดเร็ว¥จากคำตอบของเขา)

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

ลิงก์ monadic ยอมรับรายการของอักขระที่ให้ผลลอย

ลองออนไลน์! หรือดูที่ทดสอบการทดสอบในตัว

อย่างไร

โน้ตตัวแรกที่สายป้อนจะทำเฉพาะจากตัวละคร0123456789.ที่มีเลขที่มีเหลือเมื่อหารด้วยแปด[48,49,50,51,52,53,54,55,56,57,46] [0,1,2,3,4,5,6,7,0,1,6]ตัวละครเดียวที่อยู่ระหว่าง-1และ1รวมเป็น0, 1, และ89

นอกจากนี้หากเราลบเลขแปดออกจากอันดับ ( [40,41,42,43,44,45,46,47,48,49,38]) จะคงเดิม (ค่อนข้างชัดเจน) ถ้าเราลดลงครึ่งหนึ่งเหล่านี้ ( [20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) ตัวละครเท่านั้นที่มีเหลือเมื่อหารด้วยแปดซึ่งอยู่ระหว่าง-1และ1รวมอยู่และ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

เรติน่า 0.8.2 , 75 ไบต์

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

ลองออนไลน์! ลิงก์มีกรณีทดสอบ คำอธิบาย:

^[89]
10

จัดการกับกรณีของชั้นนำที่หรือ89

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.