Implementare una divisione di precisione arbitraria


15

Implementare una funzione divide(int a, int b, int c)che stampa il valore di base 10 di a/b. senza usare alcuna matematica a virgola mobile né BigInteger/ BigDecimalo librerie equivalenti di sorta. È necessario stampare almeno ccaratteri precisi all'interno dell'insieme di 0123456789., ad eccezione della (possibile) eccezione al punto 4 seguente.

  1. ae bpuò essere qualsiasi numero intero a 32 bit. Aggiornamento: se, ai fini del golf, si desidera che l'input sia primitivo a 64 bit, va bene, ma non è necessario supportare l'intero intervallo di dati a 64 bit.
  2. Non è necessario verificare che csia positivo (anche se si spera che il programma non si blocchi) in caso contrario.
  3. Il limite minimo supportato per cè 500. Va bene se il tuo programma non supporta i valori di cui csopra 500, ma va bene anche se lo fa.
  4. Per i numeri che si dividono uniformemente, è la tua scelta se stampare zero aggiuntivi (in base al valore di c) o niente.
  5. Non è necessario essere in grado di utilizzare la funzione per eseguire ulteriori attività con il quoziente, l'unico obiettivo è la stampa.
  6. Per i numeri tra -1e 1, è la tua scelta se stampare un vantaggio 0. Tuttavia, questo è l'unico scenario in cui è accettabile la stampa di uno zero iniziale e si può stampare solo uno di questi zero.
  7. È possibile utilizzare qualsiasi logica di arrotondamento / piano / soffitto preferita per l'ultimo decimale.
  8. Per una risposta negativa, è necessario stampare un vantaggio -. Questo non conta ai fini c. Tuttavia, è la vostra scelta se si desidera stampare , +o nulla per una risposta positiva.
  9. Divisione intera e modulo intero sono entrambi consentiti. Tuttavia, tieni presente che sei limitato alle primitive, a meno che tu non scelga di implementare la tua BigInteger/ BigDecimallibreria che conta per la lunghezza del tuo codice.
  10. Non hai bisogno di gestire l' bessere 0, anche se puoi se vuoi. Il tuo programma può entrare in un ciclo infinito, o crash, se b=0e non sarai penalizzato.
  11. Leggero cambio di regola per commento. Per assicurarsi che il campo di gioco è il livello, mentre ae bsono garantiti per essere di 32 numeri interi bit, è possibile utilizzare gli interi lunghi 64 bit. Se la tua lingua scelta va oltre i numeri interi a 64 bit come primitiva, non puoi mai usare quella funzionalità (fingi che sia limitata a 64 bit).
  12. Un altro punto che non è chiaro (non dovrebbe cambiare nessuna delle attuali risposte valide, però): mentre cpuò essere interpretato come il numero di caratteri stampati o il numero di spazi dopo il decimale, il programma deve utilizzare in cqualche modo in modo pertinente per decidere quanti caratteri stampare. In altre parole, divide(2,3,2)dovrebbe essere un output molto più breve di divide(2,3,500); non va bene stampare 500 caratteri senza riguardo c.
  13. In realtà non mi interessa il nome della funzione. dva bene per il golf.

Ingresso

stdinSono accettate sia una chiamata di funzione che la lettura da . Se leggi da stdin, qualsiasi carattere non presente nel set [-0123456789]viene considerato un delimitatore di argomenti.

Produzione

Personaggi stdoutcome descritto sopra.

Esempio

per divide(2,3,5), tutti i seguenti sono output accettabili:

0.666
0.667
.6666
.6667
 0.666
 0.667
 .6666
 .6667
+0.666
+0.667
+.6666
+.6667

Un altro esempio: per divide(371,3,5)quanto segue sono tutti gli output accettabili:

123.6
123.7
 123.6
 123.7
+123.6
+123.7
123.66666
123.66667
 123.66666
 123.66667
+123.66666
+123.66667

E per divide(371,-3,5)quanto segue sono tutti accettabili:

-123.6
-123.7
-123.66666
-123.66667

Per motivi di parità, potrebbe essere saggio fornire una lunghezza massima massima specifica che può essere utilizzata (primitiva o meno) a meno che non si realizzi un'implementazione più ampia, poiché a) in alcune lingue la lunghezza in bit delle primitive varia a seconda del l'architettura sottostante eb) in alcune lingue i grandi numeri sono primitivi.
Jonathan Van Matre,

@JonathanVanMatre Aggiunta la regola 11 per il tuo commento
durron597

1
Come si contano le cifre precise ? Nel tuo esempio vedo tre o quattro ma mai cinque come indica l'ultimo argomento.
Howard,

@Howard, se hai fatto 92,3,5la risposta sarebbe, ad esempio,30.67
durron597,

1
tra 370/3 = 123.333 lol
izabera,

Risposte:


5

Java, 92/128

void d(long a,int b,int c){if(a<0^b<0){a=-a;p('-');}for(p(a/b+".");c>0;c--)p((a=a%b*10)/b);}<T>void p(T x){System.out.print(x);}

Ho dovuto improvvisare in modo che ao bpotesse essere -2147483648 poiché gli interi positivi a 32 bit contano solo per 2147483647, ecco perché è adiventato a long. Ci potrebbe essere un modo migliore di gestire i risultati negativi, ma so che nessuno ( doubles sarebbero probabilmente ottenere questo al lavoro per abs(a) < abs(b)come hanno -0ma solo complemento a uno manterrebbero la precisione).

Perché due numeri di byte? Avevo bisogno di 92 byte per il calcolo e 36 per l'helper di stampa (fa System.out.printschifo; generalmente Java non è così matto).

public class Div {

    void d(long a, int b, int c) {
        if (a < 0 ^ b < 0) {
            a = -a;
            p('-');
        }
        for (p(a / b + "."); c > 0; c--) {
            p((a = a % b * 10) / b);
        }
    }

    <T> void p(T x) {
        System.out.print(x);
    }

    public static void main(String[] args) {
        final Div div = new Div();
        div.d(12345, 234, 20);
        div.p('\n');
        div.d(-12345, 234, 20);
        div.p('\n');
        div.d(234, 234, 20);
        div.p('\n');
        div.d(-234, 234, 20);
        div.p('\n');
        div.d(234, 12345, 20);
        div.p('\n');
        div.d(234, -12345, 20);
        div.p('\n');
        div.d(-234, 12345, 20);
        div.p('\n');
        div.d(-234, -12345, 20);
        div.p('\n');
        div.d(-2147483648, 2147483647, 20);
        div.p('\n');
        div.d(2147483647, -2147483648, 20);
        div.p('\n');
    }
}

Il metodo fondamentalmente esercita ciò che la maggior parte di noi ha imparato a scuola per generare le cifre decimali richieste.


Sentenza ufficiale: direi che ignorare Integer.MIN_VALUEnon va bene ma che longcome input va bene.
durron597,

È molto più breve. Ben fatto.
durron597,

@ durron597 grazie. Ancora la digitazione rigorosa e System.outfa sembrare Java ingombrante ;-) Ancora una buona sensazione, che ci sono già postate più risposte.
TheConstructor il

1
@ durron597 hai chiesto espressamente una funzione, quindi ho pensato che non contava. Se dovessi usare le importazioni, probabilmente sì.
TheConstructor il

1
Almeno non ci sono $ per ogni variabile ;-)
TheConstructor il

9

C, 98 95 89

d(a,b,c){if(a>0^b>0)a=-a,printf("-");for(printf("%d.",a/b);c--;putchar(a/b+48))a=a%b*10;}

stampa ccifre dopo il.

esempio di output:

d(2,3,5);
0.66666

d(-2,3,5);
-0.66666

d(24352345,31412,500);
775.25611231376543995925124156373360499172290844263338851394371577740990704189481726728638736788488475741754743410161721635043932255189099707118298739335285878008404431427479943970457150133706863618999108620909206672609193938622182605373742518782630841716541449127721889723672481854068508850120972876607665860180822615560932127849229593785814338469374761237743537501591748376416656055010823888959633261174073602444925506175983700496625493441996689163377053355405577486310963962816757926906914554947153953

d(-77,12346463,500);
-0.00000623660395693892250760399962321192717298873369644407471192356871761572524859953818352673150196943043525906974329409159530142357369879940514137530724386409289850866600418273638369142644334656816288195250736992448768525852302801215214430238036593962173620088603513411087855687900251270343579371679160258286118056645048869461642577311412993340683886551152342172814999729072204727783171585254821563066280601982932277851559592411203111368818745903178910429650985873444078680671541315111866451144752954

dovrebbe funzionare per -2147483647 <= a <= 2147483647, lo stesso per b. gestire il -dolore era un dolore.

versione online: ideone


Funziona per un essere -2147483648? Non conosco i compilatori c abbastanza bene da dire quale tipo intero è assegnato ai tuoi parametri.
TheConstructor il

Grazie per segnalarlo. funziona correttamente per -2147483647 <= a <= 2147483647, lo stesso per b. c'è un problema quando a = -2147483648 eb è positivo a causa di a=-a.
izabera,

Ho provato, ma alla fine ho ottenuto sostanzialmente la stessa soluzione come te. Puoi salvare un personaggio realizzando che printf("-")restituisce 1.
Thomas,

4

PHP, 108

function d($a,$b,$c){$a*$b<0&&$a*=-print'-';for($p='.';$c--;$a.=0,print$i.$p,$p='')$a-=$b*$i=($a-$a%$b)/$b;}

Funziona semplicemente emettendo il quoziente di a/ bdurante un ciclo di cpassaggi, adiventando il resto moltiplicato per 10 ad ogni iterazione.

DEMO


Produce strani risultati quando a o b sono negativi
TheConstructor il

Ho corretto l'errore per i numeri negativi. Grazie!
Razvan,

Ho appena trovato una versione 112 del tuo codice: function d($a,$b,$c){if($a*$b<0)$a*=-print'-';for($p='.';$c--;$a*=10,$p=''){$a-=$b*$i=($a-$a%$b)/$b;echo$i.$p;}}vedi valore di ritorno
TheConstructor il

Grazie. Ho anche aggiornato la tua versione e sono riuscito a vincere 1 byte in più.
Razvan,

2

Python 111

f=lambda a,b,c:'-'[a*b>=0:]+'%s'%reduce(lambda(d,r),c:(d%c*10,r+`d/c`+'.'[r!='':],),[abs(b)]*c,(abs(a),''))[-1]

Questa soluzione non viola nessuna delle regole indicate.


2

C: 72 caratteri

d(a,b,c){for(printf("%d.",a/b);c--;putchar((a=abs(a)%b*10)/abs(b)+48));}

Fa quasi del tutto quello che dovrebbe fare. Tuttavia, come alcune delle altre risposte qui forniranno valori traballanti o falliranno d(-2147483648,b,c)e d(a,-2147483648,c)poiché il valore assoluto di -2147483648 è fuori limite per una parola a 32 bit.


2

Perl, nessun calcolo aritmetico, 274 byte

Questa è la lunga divisione euclidea , che probabilmente consumerà una quantità insolita di memoria. Il più vicino che arriva alla matematica sui numeri in virgola mobile è nell'usare le operazioni di bit per analizzarli.

sub di{($v,$i,$d,$e)=(0,@_);($s,$c,$j)=$i=~s/-//g;$s^=$d=~s/-//g;
$i=~s/\.(\d+)/$j=$1,""/e;$d=~s/\.(\d+)/$c=$1,""/e;
$z=0.x+length($c|$j);$i.=$j|$z;$d.=$c|$z;
($e,$m,$z,$t)=(1.x$e,0.x$i,0.x$d,"-"x($s&1));
for(;$e;$t.="."x!$v,$v=chop$e){$t.=$m=~s/$z//g||0;$m="$m"x10}
print"$t\n"}

Esempi:

di(-355,113,238);
di(1.13,355,239);
di(27942,19175,239);
di(1,-90.09,238);
di("--10.0","----9.801",239);
di(".01",".200",239);

Produzione:

-3.141592920353982300884955752212389380530973451327433628318
584070796460176991150442477876106194690265486725663716814159
292035398230088495575221238938053097345132743362831858407079
646017699115044247787610619469026548672566371681415929203539

0.0031830985915492957746478873239436619718309859154929577464
788732394366197183098591549295774647887323943661971830985915
492957746478873239436619718309859154929577464788732394366197
183098591549295774647887323943661971830985915492957746478873

1.4572099087353324641460234680573663624511082138200782268578
878748370273794002607561929595827900912646675358539765319426
336375488917861799217731421121251629726205997392438070404172
099087353324641460234680573663624511082138200782268578878748

-0.011100011100011100011100011100011100011100011100011100011
100011100011100011100011100011100011100011100011100011100011
100011100011100011100011100011100011100011100011100011100011
100011100011100011100011100011100011100011100011100011100011

1.0203040506070809101112131415161718192021222324252627282930
313233343536373839404142434445464748495051525354555657585960
616263646566676869707172737475767778798081828384858687888990
919293949596979900010203040506070809101112131415161718192021

0.0500000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000

1

Ruby, 178

def d(a,b,c)
    n=(a<0)^(b<0)
    a=-a if n
    m=a/b-b/a
    l=m.to_s.size-1
    g=(a*10**(10+c)/b).to_s
    f=m<0?"."+"0"*(l-1)+g[0..c-l-1] : g[0..l]+"."+g[l+1..c-2]
    p n ? "-"+f : f
end

Versione online per i test.

Il trucco è moltiplicare a con un numero piuttosto alto, quindi il risultato è solo un multiplo intero dell'operazione in virgola mobile. Quindi il punto e gli zeri devono essere inseriti nel posto giusto nella stringa risultante.


Funziona con c maggiore di 350?
durron597,

L'ho provato con c = 1000 - il codice mi ha dato una risposta, forse dovrei controllare il risultato reale però ...
David Herrmann,

2
non gandare oltre 64 bit per i grandi c? Modifica: penso che tu stia usando implicitamente BigIntegerqui
durron597,

Err, gè una stringa, ma prima di chiamare to_shai creato un numero in memoria di dimensioni superiori a 64 bit
durron597

1
Questo è comprensibile - e rende il compito più impegnativo (e interessante)! È meglio eliminare la risposta o lasciarla ad altri per avere un esempio di come non implementare l'attività?
David Herrmann,

1

python 92 byte:

def d(a,b,c):c-=len(str(a/b))+1;e=10**c;a*=e;a/=b;a=str(a);x=len(a)-c;return a[:x]+'.'+a[x:]

penso che un po 'più di golf sia possibile .....


2
non eandare oltre i 64 bit per i grandi c? Modifica: penso che tu stia usando implicitamente BigIntegerqui.
durron597,

1
@ durron597 ne dubito fortemente. Va a BigInt (Long in python) ma 2 ** 45 è 48 bit. È abbastanza presunzione ?? Inoltre, Python NON ha primitivi quindi ...
Maltysen,

Se a=5e c=400poi dopo e=10**c, in esadecimale, il numero è lungo 333 cifre. Inizia 8889e7dd7f43fc2f7900bc2eac756d1c4927a5b8e56bbcfc97d39bac6936e648180f47d1396bc905a47cc481617c7...questo è più di 64 bit.
durron597,

@ durron597 400 ... ne ho bisogno
Maltysen,

1
Sì, la regola 3 dice che devi supportare fino ad almeno 500 ... Stavo cercando di impedire questa soluzione (imo banale).
durron597,

1

C 83

d(a,b,c){printf("%d.",a/b);for(a=abs(a),b=abs(b);c--&&(a=a%b*10);)putchar(a/b+48);}

Stessa idea che ho usato nella mia implementazione di Python


Molto bella! Tuttavia, si bloccad(-2147483648,-1,10)
durron597,
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.