Implementieren Sie eine beliebige Präzisionsteilung


15

Implementieren Sie eine Funktion divide(int a, int b, int c), die den Basis-10-Wert von ausgibt a/b. ohne Verwendung von Gleitkomma-Mathematik oder BigInteger/ BigDecimalund äquivalenten Bibliotheken. Mit Ausnahme der (möglichen) Ausnahme in Punkt 4 müssen mindestens cgenaue Zeichen innerhalb des Satzes 0123456789.gedruckt werden.

  1. aund bkann eine beliebige 32-Bit-Ganzzahl sein. Update: Wenn Sie zu Golfzwecken eine Eingabe mit 64-Bit-Grundelementen wünschen, ist dies in Ordnung, Sie müssen jedoch nicht den gesamten 64-Bit-Datenbereich unterstützen.
  2. Sie müssen nicht überprüfen, ob dies cpositiv ist (obwohl Ihr Programm hoffentlich nicht abstürzt), wenn dies nicht der Fall ist.
  3. Die unterstützte Mindestobergrenze für cist 500. Es ist in Ordnung, wenn Ihr Programm die cobigen Werte nicht unterstützt 500, aber es ist auch in Ordnung, wenn dies der Fall ist.
  4. Bei gleichmäßig verteilten Zahlen können Sie wählen, ob Sie zusätzliche Nullen (basierend auf dem Wert von c) oder nichts drucken möchten .
  5. Sie müssen die Funktion nicht verwenden können, um weitere Aufgaben mit dem Quotienten auszuführen. Das einzige Ziel ist das Drucken.
  6. Bei Zahlen zwischen -1und 1haben Sie die Wahl, ob Sie einen Zeilenumbruch drucken möchten 0. Dies ist jedoch das einzige Szenario, in dem das Drucken einer führenden Null zulässig ist und Sie möglicherweise nur eine solche Null drucken.
  7. Sie können für die letzte Dezimalstelle eine beliebige Rundungs- / Floor- / Ceil-Logik verwenden, die Sie bevorzugen.
  8. Für eine negative Antwort müssen Sie eine führende drucken -. Dies zählt nicht dazu c. Aber es ist Ihre Wahl , wenn Sie drucken möchten , +oder nichts für eine positive Antwort.
  9. Sowohl Ganzzahlteilung als auch Ganzzahlmodul sind zulässig. Denken Sie jedoch daran , dass Sie auf Primitiven beschränkt sind, es sei denn , Sie wählen Sie Ihre eigene implementieren BigInteger/ BigDecimalBibliothek , die zählt gegen Ihre Codelänge.
  10. Sie müssen nicht behandeln müssen bsein 0, wenn Sie können , wenn Sie wollen. Ihr Programm kann in eine Endlosschleife eintreten oder abstürzen, wenn b=0, und Sie werden nicht bestraft.
  11. Leichte Regeländerung pro Kommentar. Um sicherzustellen, dass das Spielfeld eben ist aund bgarantiert 32-Bit-Ganzzahlen aufweist, können Sie 64-Bit-Ganzzahlen verwenden. Wenn Ihre gewählte Sprache mehr als 64-Bit-Ganzzahlen als Grundelement enthält, können Sie diese Funktionalität zu keinem Zeitpunkt verwenden (so tun, als wäre sie auf 64-Bit begrenzt).
  12. Ein weiterer Punkt, der unklar ist (er sollte jedoch keine der aktuell gültigen Antworten ändern): Während er centweder als die Anzahl der gedruckten Zeichen oder die Anzahl der Nachkommastellen interpretiert werden kann, muss Ihr Programm sie cauf eine relevante Weise verwenden um zu entscheiden, wie viele Zeichen gedruckt werden sollen. Mit anderen Worten divide(2,3,2)sollte die Ausgabe viel kürzer sein als divide(2,3,500); Es ist nicht in Ordnung, 500 Zeichen ohne Rücksicht auf zu drucken c.
  13. Der Name der Funktion ist mir eigentlich egal. dist für Golfzwecke in Ordnung.

Eingang

Es wird sowohl ein Funktionsaufruf als auch ein Lesevorgang stdinakzeptiert. Wenn Sie von lesen stdin, wird jedes Zeichen, das nicht in der Menge enthalten [-0123456789]ist, als Argumentbegrenzer betrachtet.

Ausgabe

Zeichen bis stdoutwie oben beschrieben.

Beispiel

für divide(2,3,5)alle die folgenden sind akzeptabel Ausgänge:

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

Ein weiteres Beispiel: Für divide(371,3,5)die folgenden sind alle akzeptablen Ausgaben:

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

Und für divide(371,-3,5)die folgenden sind alle akzeptabel:

-123.6
-123.7
-123.66666
-123.66667

Aus Gründen gleicher Ausgangsbedingungen kann es sinnvoll sein, eine bestimmte maximale Bitlänge anzugeben, die verwendet werden kann (primitiv oder anderweitig), es sei denn, Sie haben eine eigene größere Implementierung erstellt, da a) die Bitlänge von Primitiven in einigen Sprachen abhängig von variiert die zugrunde liegende Architektur und b) in einigen Sprachen große Anzahl Typen sind Primitiven.
Jonathan Van Matre

@JonathanVanMatre Regel 11 wurde Ihrem Kommentar
hinzugefügt

1
Wie zählt man genaue Ziffern ? In Ihrem Beispiel sehe ich drei oder vier, aber niemals fünf, wie das letzte Argument anzeigt.
Howard

@Howard, wenn du 92,3,5das tust, wäre die Antwort zum Beispiel30.67
durron597

1
btw 370/3 = 123.333 lol
izabera

Antworten:


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

Ich musste improvisieren, damit aoder bkonnte -2147483648 als positive 32-Bit-Ganzzahlen nur gegen 2147483647 zählen, deshalb awurde ein long. Es könnte eine bessere Möglichkeit geben, mit negativen Ergebnissen umzugehen, aber ich weiß, dass es keine gibt ( doublewahrscheinlich würde dies funktionieren, abs(a) < abs(b)da es sie gibt, -0aber nur das Komplement der einen würde die Präzision bewahren).

Warum zwei Bytes? Ich brauchte 92 Bytes für die Berechnung und 36 für den Print-Helfer ( System.out.printsaugt; Java ist im Allgemeinen nicht so golfen).

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

Die Methode verwendet im Wesentlichen das, was die meisten von uns in der Schule gelernt haben, um die gewünschten Dezimalstellen zu generieren.


Offizielle Entscheidung: Ich würde sagen, dass Ignorieren Integer.MIN_VALUEnicht in Ordnung ist, aber das longals Eingabe ist in Ordnung.
Durron597

Das ist viel kürzer. Schön gemacht.
Durron597

@durron597 danke. Immer noch das strikte Tippen und System.outJava sperrig machen ;-) Immer noch ein gutes Gefühl, dass es schon längere Antworten gibt.
TheConstructor

1
@durron597 Du hast speziell nach einer Funktion gefragt, damit ich erfahre, dass sie nicht zählt. Wenn ich Importe verwenden müsste dann wohl ja.
TheConstructor

1
Zumindest gibt es keine $ für jede Variable ;-)
TheConstructor

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

druckt cZiffern nach dem.

Beispielausgabe:

d(2,3,5);
0.66666

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

d(24352345,31412,500);
775.25611231376543995925124156373360499172290844263338851394371577740990704189481726728638736788488475741754743410161721635043932255189099707118298739335285878008404431427479943970457150133706863618999108620909206672609193938622182605373742518782630841716541449127721889723672481854068508850120972876607665860180822615560932127849229593785814338469374761237743537501591748376416656055010823888959633261174073602444925506175983700496625493441996689163377053355405577486310963962816757926906914554947153953

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

sollte für -2147483647 <= a <= 2147483647 funktionieren, dasselbe gilt für b. Der Umgang mit dem -war ein Schmerz.

Online-Version: ideone


Funktioniert das für ein Wesen -2147483648? Sie kennen die c-Compiler nicht gut genug, um festzustellen, welcher Integer-Typ Ihren Parametern zugewiesen ist.
TheConstructor

danke für den Hinweis. es funktioniert korrekt für -2147483647 <= a <= 2147483647, dasselbe für b. Es gibt ein Problem, wenn a = -2147483648 und b aufgrund positiv ist a=-a.
Izabera

Ich habe es versucht, habe aber letztendlich im Wesentlichen die gleiche Lösung wie Sie gefunden. Sie können ein Zeichen speichern, indem Sie feststellen, dass printf("-")1 zurückgegeben wird.
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;}

Es funktioniert durch einfaches Ausgeben des Quotienten aus a/ bwährend einer cSchrittschleife, awobei der Rest bei jeder Iteration mit 10 multipliziert wird.

DEMO


Erzeugt seltsame Ergebnisse, wenn a oder b negativ sind
TheConstructor

Ich habe den Fehler für negative Zahlen behoben. Vielen Dank!
Razvan

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;}}
Wir haben

Vielen Dank. Ich habe sogar deine Version aktualisiert und es geschafft, ein zusätzliches Byte zu gewinnen.
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]

Diese Lösung verletzt keine der angegebenen Regeln.


2

C: 72 Zeichen

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

Es macht fast alles, was es machen soll. Jedoch wird es wie einige der anderen Antworten hier Wonky-Werte geben oder scheitern d(-2147483648,b,c)und d(a,-2147483648,c)da der absolute Wert von -2147483648 für ein 32-Bit-Wort außerhalb der Grenzen liegt.


2

Perl, keine Arithmetik, 274 Bytes

Dies ist eine euklidische lange Teilung, die wahrscheinlich ungewöhnlich viel Speicher verbraucht. Der beste Weg, um Gleitkommazahlen zu berechnen, ist die Verwendung von Bitoperationen, um sie zu analysieren.

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"}

Beispiele:

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

Ausgabe:

-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

Rubin, 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

Online-Version zum Testen.

Der Trick besteht darin, a mit einer ziemlich hohen Zahl zu multiplizieren , sodass das Ergebnis nur ein ganzzahliges Vielfaches der Gleitkommaoperation ist. Dann müssen der Punkt und die Nullen an der richtigen Stelle in die resultierende Zeichenfolge eingefügt werden.


Funktioniert das für c größer als 350?
Durron597

Ich habe es mit c = 1000 getestet - der Code gab mir eine Antwort, vielleicht sollte ich das tatsächliche Ergebnis überprüfen ...
David Herrmann

2
kommt gman bei großen über 64 bits hinaus c? Bearbeiten: Ich glaube, Sie verwenden implizit BigIntegerhier
Durron597

Err, gist eine Zeichenfolge, aber bevor Sie anrufen, haben to_sSie eine Nummer im Speicher erstellt, die
größer als

1
Das ist verständlich - und macht die Aufgabe anspruchsvoller (und interessanter)! Ist es besser, die Antwort zu löschen oder anderen zu überlassen, ein Beispiel dafür zu geben, wie die Aufgabe nicht implementiert werden kann?
David Herrmann

1

Python 92 Bytes:

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:]

Ich denke, noch mehr Golf ist möglich .....


2
kommt ejenseits von 64 Bit für große c? Bearbeiten: Ich denke, Sie verwenden implizit BigIntegerhier.
Durron597

1
@ durron597 Das bezweifle ich sehr. Es geht an BigInt (Long in Python), aber 2 ** 45 ist 48 Bit. Ist das genug Vorraussetzung? Außerdem hat Python KEINE Primitive, also ...
Maltysen

Wenn a=5und c=400dann danach e=10**c, in hex, ist die Zahl 333 Stellen lang. Es beginnt, 8889e7dd7f43fc2f7900bc2eac756d1c4927a5b8e56bbcfc97d39bac6936e648180f47d1396bc905a47cc481617c7...dies ist mehr als 64 Bit.
Durron597

@ Durron597 400 ... brauche ich das
Maltysen

1
Ja, Regel 3 besagt, dass Sie bis zu 500 unterstützen müssen ... Ich habe versucht, diese (imo triviale) Lösung zu verhindern.
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);}

Dieselbe Idee, die ich in meiner Python-Implementierung verwendet habe


Sehr schön! Es stürzt jedoch ab amd(-2147483648,-1,10)
durron597
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.