Arrotondamento soddisfacente


16

Arrotondamento soddisfacente

Sai quando sei in classe di scienze e hai chiesto di arrotondare a 2 sig fichi, ma la tua risposta è 5.2501...? Dovresti arrotondare a 5.3, ma è così insoddisfacente! Arrotondando a 5.3, si ottiene un totale di 0,05, che è una grande quantità rispetto a 0,1 (il valore del posto a cui si sta arrotondando)! Quindi aiutami a arrotondare in modo soddisfacente.

Per arrotondare in modo soddisfacente, è necessario arrotondare alla prima cifra che si incontra che produce un errore relativamente piccolo - meno della metà dell'errore massimo possibile durante l'arrotondamento. Fondamentalmente, devi arrotondare ogni volta che incontri 0, 1, 8 o 9. Se ciò non accade, restituisci l'input così com'è. Non arrotondare a zero o a quelli iniziali - questo non sembra soddisfacente.

Ingresso

Un valore stringa o float che rappresenta un numero decimale non negativo.

Produzione

Lo stesso numero decimale arrotondato in modo soddisfacente, in formato stringa o float.

Esempi

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

Questa è una sfida di , quindi vince il codice più corto!



Le stringhe come quelle 036.40000considerate sono un output valido?
Arnauld,

1
Possiamo supporre che .0verrà data una parte per gli interi? Inoltre, 0non è positivo.
Erik the Outgolfer,

@EriktheOutgolfer No, non puoi - anche grazie, cambiato in non negativo.
Quintec,

1
Quindi 19round a 20ma 0.19round a 0? Perché?
Neil,

Risposte:


2

JavaScript (ES6),  100 99 98  78 byte

Accetta l'input come stringa. Restituisce un float.

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

Provalo online!

Come?

Per prima cosa anteponiamo uno 0 alla stringa di input, in modo da avere una cifra prima di un possibile 8 o 9 , che deve innescare immediatamente l'arrotondamento.

La bandiera j è impostata su 1 fintanto che stiamo cercando una cifra su cui possiamo effettuare un arrotondamento soddisfacente, e impostata su 0 seguito.

Poiché è stato aggiunto uno 0 alla stringa che stiamo attraversando ma s è rimasto invariato, d contiene il carattere corrente e s[i] punta al carattere successivo .

Usiamo il seguente codice per caricare la cifra successiva in n , saltando un possibile separatore decimale:

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

Sebbene le stringhe siano immutabili in JavaScript, l'espressione ++s[i]restituirà s[i]+1 se contiene un valore numerico, anche se s[i] non è effettivamente incrementato. Pertanto, l'espressione !++s[i]viene valutata ad false (costretto a 0 ) per tutte le cifre (compresi 0 ) e true (costretti a 1 ) per il separatore decimale ".".

d + --jn01d + j--n89j00d1


1
E la palla da flipper / gomma cade in un fossato! :)
Quintec,

2

Rubino , 79 77 69 67 65 byte

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

Provalo online!

Spiegazione

  • ->n Prendi input come stringa
  • z=n+".0"Creare una stringa temporanea zche garantisca contenere un punto e una cifra rilevante.
  • i=z=~/\./Determinare la posizione del punto decimale in ze assegnare a i.
  • z[i]='' Rilascia il punto in modo che non si frapponga ulteriormente.
  • z=~/(?!^)[01]|8|9/Determina la posizione di non partenza 0-1o qualsiasi 8-9, a seconda dell'evento che si verifica per primo.
  • (...)-i Questa differenza sarà il numero di cifre decimali da mantenere, negativo se arrotonderemo a sinistra del punto.
  • n.to_f.round ... Converti in float e fai l'arrotondamento.

1

Gelatina , 34 byte

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

Provalo online!

-1 grazie a Jonathan Allan .


Perché ŒV? Penso Vche funzionerà anche.
Jonathan Allan,

@JonathanAllan Nope. (fondamentalmente stranezze di arrotondamento del banchiere)
Erik the Outgolfer

Oh, perché non agisce sull'input? Prova _>¥0ɓVærcome la mia (ho perso l'uso della diadica veloce, quindi grazie!)
Jonathan Allan,

@JonathanAllan Ah, uso intelligente delle catene, grazie.
Erik the Outgolfer,

1

Gelatina ,  30  29 byte

-1 grazie a Erik the Outgolfer (uso della diade veloce ¥dalla sua risposta)

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

Un collegamento monadico che accetta un elenco di caratteri che produce un float.

Provalo online! Oppure vedi la suite di test .

Come

Prima nota che la stringa di input è composta esclusivamente dai caratteri 0123456789.che hanno ordinali [48,49,50,51,52,53,54,55,56,57,46], che hanno resti se divisi per otto di [0,1,2,3,4,5,6,7,0,1,6]. Gli unici caratteri che si trovano tra -1e 1inclusiva sono 0, 1, 8, e 9.

Inoltre se sottraggiamo otto dagli ordinali ( [40,41,42,43,44,45,46,47,48,49,38]) vale lo stesso (abbastanza ovviamente). Se dimezziamo questi ( [20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]) gli unici caratteri che hanno resti quando divisi per otto che sono tra -1e 1compreso sono 8e 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 byte

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

Provalo online! Il link include casi di test. Spiegazione:

^[89]
10

Gestire il caso di un leader 8o 9.

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

Se è presente un non-lead 0o 1, quindi azzeralo e il resto della stringa viene espulso. Inoltre, se c'è un 8o 9, quindi lascialo, ma azzera il resto della stringa. (Ma lasciare invariato il punto decimale in entrambi i casi.)

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

Se c'è ancora un 8o 9a questo punto, azzeralo e incrementa la cifra precedente (possibilmente prima del punto decimale).

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

Elimina gli zeri finali se sono dopo un punto decimale, ma elimina il punto decimale solo se non ci sono altre cifre tra di loro.


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

Provalo online!

//_: 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 # (compilatore interattivo 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();}

Provalo online!

Può essere più breve se ho usato i doppi invece dei decimali, ma ho usato i decimali per preservare la precisione, altrimenti un numero come 547.4726 sarebbe 547.472595214844.

C # (compilatore interattivo 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();}

Provalo online! (Versione meno accurata)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.