Задовільне округлення


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вважається, є дійсним?
Арнольд

1
Чи можна припустити, що .0частина буде надана для цілих чисел? Крім того, 0не є позитивним.
Ерік Аутгольфер

@EriktheOutgolfer Ні, ви не можете - також спасибі, змінені на негативні.
Квінтек

1
Так 19раунди до, 20але 0.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)

Спробуйте в Інтернеті!

Як?

Спочатку додаємо ведучий 0 до вхідного рядка, щоб ми гарантували цифру перед можливим провідним 8 або 9 , яке повинно запустити округлення відразу.

Прапор j встановлено на 1 до тих пір, поки ми шукаємо цифру, за якою ми можемо виконати задовільне округлення, і встановимо 0 після цього.

Оскільки до рядка, який ми проходимо, було додано провідний 0 а s залишився незмінним, d містить поточний символ і s[i] вказує на наступний символ.

Ми використовуємо наступний код для завантаження наступної цифри в n , пропускаючи можливий десятковий роздільник:

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

Хоча рядки незмінні в JavaScript, вираз ++s[i]поверне s[i]+1 якщо він містить числове значення, навіть якщо s[i] насправді не збільшується. Тому вираз !++s[i]оцінюється в false (примусово до 0 ) для всіх цифр (включаючи 0 ) і до true (примусово до 1 ) для десяткового роздільника"." .

Коли відбувається округлення, ми отримуємо, d + --jякщо наступна цифра n дорівнює 0 або 1 (а це не провідна цифра вихідного вводу) і d + j--якщо n дорівнює 8 або 9 . Отже, j в обох випадках встановлено на 0 але в першому випадку додаємо 0 до d (округлення вниз) та 1 у другому (округлення).


1
І куля з пінболу / гуми потрапляє в кювет! :)
Квінтек

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/Визначте положення нестартового 0-1чи будь-якого8-9 , що залежить від першого.
  • (...)-i Ця різниця буде числом десяткових знаків, які слід зберегти, негативними, якщо ми будемо округляти зліва від крапки.
  • n.to_f.round ... Перетворити в плавати і зробити округлення.

1

Желе , 34 байти

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

Спробуйте в Інтернеті!

-1 завдяки Джонатану Аллану .


Чому ŒV? Я думаю V, теж буде працювати.
Джонатан Аллан

@JonathanAllan Nope. (в основному
вигадки

О, тому що це не діє на вхід? Спробуйте, _>¥0ɓVærяк моє (я пропустив використання діадіка швидко, тому теж дякую!)
Джонатан Аллан

@JonathanAllan Ах, розумне використання ланцюгів, дякую.
Ерік Аутгольфер

1

Желе ,  30  29 байт

-1 спасибі Еріку Попелицеві (використання діадічного швидкого ¥з його відповіді)

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

Монадична посилання, що приймає список символів, який дає поплавок.

Спробуйте в Інтернеті! Або дивіться тест-люкс .

Як

Спершу зауважте, що рядок введення складається виключно з символів, 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, 8, і9 .

Крім того, якщо відняти вісім від порядків ( [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включно 8і 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

Сітківка 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]

Якщо в цій точці все ще є 8a або a 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();}

Спробуйте в Інтернеті! (Менш точна версія)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.