Nachkommastellen

23

Schreiben Sie ein Programm oder eine Funktion, die mit zwei Ganzzahlen a, b eine Zeichenfolge ausgibt, die eine Dezimalzahl enthält, die den Bruch a / b genau darstellt .

Wenn a / b eine Ganzzahl ist, geben Sie einfach den Wert ohne Dezimalpunkt oder führende Nullen aus:

123562375921304812375087183597 / 2777 -> 44494913907563850333124661
81 / 3 -> 27
-6 / 2 -> -3

Wenn a / b keine Ganzzahl ist, sondern eine endliche Darstellung in der Basis 10 hat, geben Sie den Wert ohne führende oder nachfolgende Nullen aus (mit Ausnahme einer einzelnen Null vor dem Punkt):

1 / 2 -> 0.5
3289323463 / -250000000 -> -13.157293852

Schließlich wird , wenn , und nur wenn (also keine 0.999...) a / b nicht ganze Zahl ist , und nicht über eine finite Darstellung, die endliche Ausgangsteil , gefolgt von der sich wiederholenden Teil in Klammern. Der sich wiederholende Teil muss so klein wie möglich sein und so früh wie möglich beginnen.

-1 / 3 -> -0.(3)
235 / 14 -> 16.7(857142)
123 / 321 -> 0.(38317757009345794392523364485981308411214953271028037)
355 / 113 -> 3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)

Ihr Programm muss auf einem modernen Desktop-PC in weniger als 10 Sekunden für alle oben genannten Beispiele funktionieren. Das kleinste Programm in Bytes gewinnt.

orlp
quelle
@DestructibleWatermelon Dies ist in nahezu allen Sprachen möglich, einschließlich Turing Tarpits. (Diese könnten jedoch mit dem Zeitlimit zu kämpfen haben.)
Dennis
@DestructibleWatermelon Ich hatte den Eindruck, dass die meisten Sprachen vollständig sind.
Orlp
Können wir mit Sicherheit davon ausgehen, dass der Bruch nicht etwa 0,33333333333336333 ... lautet?
brianush1
2
Dies scheint ein langwieriger Weg zu sein, um nach Lösungen für PE26 zu fragen ;)
Conor O'Brien
1
Verallgemeinerung dieser Frage ; auch verwandt .
Peter Taylor

Antworten:

3

Perl 6 ,  63 58  50 Bytes

{->$a,$b {$a~"($b)"x?$b}(|($^a.FatRat/$^b).base-repeating(10))}
{->\a,$b {a~"($b)"x?$b}(|($^a.FatRat/$^b).base-repeating)}
{$/=($^a.FatRat/$^b).base-repeating;$0~"($1)"x?$1}

Probier es aus

Wenn es Ihnen egal ist, dass es nur mit Nennern funktioniert, die in eine 64-Bit-Ganzzahl passen, kann es auf nur 43 Byte verkürzt werden:

{$/=($^a/$^b).base-repeating;$0~"($1)"x?$1}

Erweitert:

{
  # store in match variable so that we can
  # use 「$0」 and 「$1」
  $/ = (

    # turn the first value into a FatRat so that
    # it will continue to work for all Int inputs
    $^a.FatRat / $^b

  ).base-repeating;

  # 「$0」 is short for 「$/[0]」 which is the non-repeating part
  $0

  # string concatenated with
  ~

  # string repeat once if $1 is truthy (the repeating part)
  # otherwise it will be an empty Str
  "($1)" x ?$1
}
Brad Gilbert b2gills
quelle
Die Art und Weise, wie Sie Ihre Antwort formatiert haben, ist verwirrend. Sie sollten Ihre alten Programme entfernen, da es im Moment wie ein mehrzeiliges Programm aussieht.
mbomb007
@ mbomb007 Der Hauptgrund, warum ich Golf poste, ist das Marketing und die Schulung von Perl 6. Also lasse ich alte Versionen drin, um mehr von der Sprache zu zeigen. Das ist auch der Grund, warum ich selten einen poste, bis ich dort eine Erklärung habe. Ich habe es so geändert, dass sich die verschiedenen Beispiele in verschiedenen Codeblöcken befinden.
Brad Gilbert b2gills
Alte Versionen sind immer im Bearbeitungsverlauf des Posts sichtbar.
mbomb007
@ mbomb007 Nicht, wenn ich erst warten muss, nachdem ich verschiedene Schreibweisen ausprobiert habe.
Brad Gilbert b2gills
Dann bearbeiten Sie einfach alle 5 Minuten einen.
mbomb007
8

Python 2, 174 Bytes

x,y=input()
a=abs(x)
b=abs(y)
r=a%b*10
L=[]
M=''
while~-(r in L):L+=r,;M+=str(r/b);r=r%b*10
i=L.index(r)
t=M[:i]+"(%s)"%M[i:]*(M[i:]>'0')
print"-%d."[x*y>=0:(t>'')+3]%(a/b)+t

Ich bin nicht ganz überzeugt von der Gültigkeit dieser Antwort, aber es hat für die obigen Testfälle und andere Testfälle funktioniert, die ich darauf geworfen habe. Es sieht allerdings nach einem richtigen Durcheinander aus, daher bin ich mir sicher, dass es viel Platz zum Golfen gibt.

Bei der Ersteinrichtung werden für beide Argumente Absolutwerte verwendet, um sicherzustellen, dass es sich um nichtnegative Zahlen handelt (die Vorzeichenberechnung wird für später gespeichert), und der Quotiententeil des Ergebnisses wird an Pythons Arithmetik mit willkürlicher Genauigkeit delegiert. Der Bruchteil wird mit dem Algorithmus der Grundschuleinteilung erledigt, bis wir im Rest eine Wiederholung erhalten. Wir schauen dann nach, wann wir diese Wiederholung das letzte Mal gesehen haben, um den Punkt zu erhalten, und konstruieren den String entsprechend.

Beachten Sie, dass der Algorithmus aufgrund der O (n) -Operation eigentlich ziemlich langsam ist in, aber für die Beispiele schnell genug.

Sp3000
quelle
5

Batch, 349 344 Bytes

@echo off
set/ad=%2,i=%1/d,r=%1%%d
if not %r%==0 set i=%i%.&if %r% leq 0 set/ar=-r&if %i%==0 set i=-0.
set d=%d:-=%
set/ae=d
:g
if %r%==0 echo %i%&exit/b
set/ag=-~!(e%%2)*(!(e%%5)*4+1)
if not %g%==1 set/ae/=g&call:d&goto g
set/as=r
set i=%i%(
:r
call:d
if %r%==%s% echo %i%)&exit/b
goto r
:d
set/ar*=10,n=r/d,r%%=d
set i=%i%%n%

Bearbeiten: 5 Bytes durch Entfernen unnötiger Zeichen gespeichert. "Ungolfed":

@echo off
set /a d = %2
set /a i = %1 / d
set /a r = %1 % d
if not %r%==0 (
    set i=%i%.                  Decimal point is required
    if %r% leq 0 (
        set /a r = -r           Get absolute value of remainder
        if %i%==0 set i=-0.     Fix edge case (-1/3 = 0 remainder -1)
    )
)
set d = %d:-=%                  Get absolute value of divisor
set /a e = d
:g
if %r%==0 echo %i% & exit /b    Finished if there's no remainder
set /a g = gcd(e, 10)           Loop through nonrecurring decimals
if not %g%==1 (
    set /a e /= g
    call :d
    goto g
)
set /a s = r                    Save remainder to know when loop ends
set i=%i%(
:r
call :d
if %r%==%s% echo %i%)&exit/b
goto r
:d                              Add the next decimal place
set /a r *= 10
set /a n = r / d
set /a r %= d
set i=%i%%n%
Neil
quelle
2
Ich habe keine Ahnung, wie das funktioniert, aber ich empfehle Ihnen, dass Sie es in Batch lmao
Alexander - Reinstate Monica
Ich bin beeindruckt von den Fähigkeiten von set /a.
Joe
2

Java, 625 605

Golf Code:

import static java.math.BigInteger.*;
String f(BigInteger a, BigInteger b){BigInteger[]r=a.divideAndRemainder(b);String s=r[0].toString();if(r[1].signum()<0)s="-"+s;if(!ZERO.equals(r[1])){s+='.';List<BigInteger>x=new ArrayList();List<BigInteger>y=new ArrayList();for(BigInteger d=TEN.multiply(r[1].abs());;){BigInteger[]z=d.divideAndRemainder(b.abs());int i=y.indexOf(z[1]);if(i>-1&&i==x.indexOf(z[0])){for(int j=0;j<i;++j)s+=x.get(j);s+='(';for(int j=i;j<x.size();++j)s+=x.get(j);s+=')';break;}x.add(z[0]);y.add(z[1]);if(ZERO.equals(z[1])){for(BigInteger j:x)s+=j;break;}d=TEN.multiply(z[1]);}}return s;}

Hinweis: Ich zähle den statischen Import als Teil der Funktion für Golfzwecke.

Diese Funktion beginnt mit dem Divisionsergebnis. Bei Bedarf werden der ganzzahlige Teil und das Vorzeichen hinzugefügt. Wenn es dann einen Rest gibt, führt es eine lange Division der Basis 10 durch. Führen Sie bei jedem Schritt die Unterteilung durch. Speichern Sie die berechnete Ziffer und den Rest in zwei Listen. Wenn wir wieder auf dieselbe Ziffer und denselben Rest stoßen, gibt es einen wiederholten Teil und wir wissen, bei welchem ​​Index er beginnt. Der Code fügt entweder die Ziffern (keine Wiederholung) oder die Vorwiederholungsziffern und dann die in Klammern gesetzten Wiederholungsziffern hinzu.

Dies ist vor allem wegen ein bisschen groß BigInteger. Wenn die Eingänge nicht einmal übergelaufen sind long, könnte es etwas kürzer sein. Ich gehe jedoch davon aus, dass es Möglichkeiten gibt, diesen Eintrag zu verbessern.

Ungolfed Code mit Hauptmethode zum Testen:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import static java.math.BigInteger.*;

public class FractionToExactDecimal {

  public static void main(String[] args) {
    // @formatter:off
    String[][] testData = new String[][] {
      { "123562375921304812375087183597", "2777", "44494913907563850333124661" },
      { "81", "3", "27" },
      { "-6", "2", "-3" },
      { "1", "2", "0.5" },
      { "3289323463", "-250000000", "-13.157293852" },
      { "-1", "3", "-0.(3)" },
      { "235", "14", "16.7(857142)" },
      { "123", "321", "0.(38317757009345794392523364485981308411214953271028037)" },
      { "355", "113", "3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)" }
    };
    // @formatter:on

    for (String[] data : testData) {
      System.out.println(data[0] + " / " + data[1]);
      System.out.println("  Expected -> " + data[2]);
      System.out.print("    Actual -> ");
      System.out.println(new FractionToExactDecimal().f(new BigInteger(data[0]), new BigInteger(data[1])));
      System.out.println();
    }
  }

  // Begin golf
  String f(BigInteger a, BigInteger b) {
    BigInteger[] r = a.divideAndRemainder(b);
    String s = r[0].toString();
    if (r[1].signum() < 0) s = "-" + s;
    if (!ZERO.equals(r[1])) {
      s += '.';
      List<BigInteger> x = new ArrayList();
      List<BigInteger> y = new ArrayList();
      for (BigInteger d = TEN.multiply(r[1].abs());;) {
        BigInteger[] z = d.divideAndRemainder(b.abs());
        int i = y.indexOf(z[1]);
        if (i > -1 && i == x.indexOf(z[0])) {
          for (int j = 0; j < i; ++j)
            s += x.get(j);
          s += '(';
          for (int j = i; j < x.size(); ++j)
            s += x.get(j);
          s += ')';
          break;
        }
        x.add(z[0]);
        y.add(z[1]);
        if (ZERO.equals(z[1])) {
          for (BigInteger j : x)
            s += j;
          break;
        }
        d = TEN.multiply(z[1]);
      }
    }
    return s;
  }
  // End golf
}

Programmausgabe:

123562375921304812375087183597 / 2777
  Expected -> 44494913907563850333124661
    Actual -> 44494913907563850333124661

81 / 3
  Expected -> 27
    Actual -> 27

-6 / 2
  Expected -> -3
    Actual -> -3

1 / 2
  Expected -> 0.5
    Actual -> 0.5

3289323463 / -250000000
  Expected -> -13.157293852
    Actual -> -13.157293852

-1 / 3
  Expected -> -0.(3)
    Actual -> -0.(3)

235 / 14
  Expected -> 16.7(857142)
    Actual -> 16.7(857142)

123 / 321
  Expected -> 0.(38317757009345794392523364485981308411214953271028037)
    Actual -> 0.(38317757009345794392523364485981308411214953271028037)

355 / 113
  Expected -> 3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)
    Actual -> 3.(1415929203539823008849557522123893805309734513274336283185840707964601769911504424778761061946902654867256637168)

quelle
Nett! Ich denke, Sie können ein paar Bytes sparen, indem Sie diese Funktion zu einer Zeichenfolge machen und dieses eine Leerzeichen entfernen a, BigInteger. Ich denke auch du könntest alias BigInteger.TENund BigInteger.ZERO.
FryAmTheEggman
@FryAmTheEggman danke, ich habe nicht bemerkt, dass der statische Import über die ausführlicheren Referenzen Speicherplatz spart. Es tut. Ich fand auch ein paar andere Dinge, die ich übersehen hatte, wie while (true)->, for (;;)die es mir auch ermöglichten, Dinge in den forInitialisierer einzufügen und ein weiteres Byte zu speichern.
Wie wäre es zuerst mit der Erweiterung von BigInteger? Zweitens genügt ein wiederholter Rest, um zu zeigen, dass er sich wiederholt. Wenn Sie die Eingabe auf int beschränken, können Sie ein int [] mit dem Rest als Index und dem Index als Wert verwenden, wenn dies sinnvoll ist.
JollyJoker
@JollyJoker, das BigInteger erweitert, würde das Schreiben einer ganzen Klasse erfordern, um Platz zu sparen, und ich bezweifle ernsthaft, dass der Kompromiss funktionieren würde. Außerdem kann ich die Eingabe nicht einschränken. Auf jeden Fall enthält BigIntegermein Code acht Instanzen , und ich sehe nicht, wie es sich auszahlt, wenn ich mehr Code hinzufüge, um sie auf einen einzelnen Zeichenklassennamen zu verkleinern. Und mit Sicherheit Code hinzufügen, um damit umzugehenint[] (was BigInteger bereits intern tut) wird meine Antwort nur aufblähen lassen.
@ JollyJoker Es ist auch erwähnenswert, dass ich, wenn ich nicht jede BigInteger Methode überschreibe , die ich aufrufe , um eine Instanz der Unterklasse zurückzugeben, mehrere Casts hinzufügen muss, die den Code weiter aufblähen. Zusätzlich zu den verschwendeten Bytes für den Overhead einer Unterklasse würde dies sicherlich die Codegröße erhöhen.
1

PHP, 277 Bytes

list(,$n,$d)=$argv;$a[]=$n;$n-=$d*$r[]=$n/$d^0;!$n?:$r[]=".";while($n&&!$t){$n*=10;$n-=$d*$r[]=$n/$d^0;$t=in_array($n%=$d,$a);$a[]=$n;}if($t){$l=count($a)-($p=array_search(end($a),$a));echo join(array_slice($r,0,2+$p))."(".join(array_slice($r,2+$p,$l)).")";}else echo join($r);
Jörg Hülsermann
quelle
0

Mathematica 198 Bytes

i=Integer;t=ToString;a_~h~b_:=f[a/b];f@q_i:= t@q;
f@q_:=""<>{t@IntegerPart[q],".",RealDigits[FractionalPart[q]][[1]]//.{{x___,{k__i}}:> {x,"("<>(t/@{k})<>")"},{x__i,j___String}:>""<> {""<>t/@{x},j}}}

Ungolfed

(* hand over quotient of a, b to function f *)
h[a_, b_] := f[a/b];

(* if the quotient is an integer, return it as a string *)
f[q_Integer] := ToString@q;

(* otherwise, return the integer part, followed by a decimal point ...*)
f[q_] := "" <> {ToString@IntegerPart[q], ".", 

   (* replacing the repeating part (if it exists) between parentheses *)
   RealDigits[FractionalPart[q]][[1]] //. {{x___, {i__Integer}} :> {x, "(" <>(ToString /@ {i}) <> ")"},

   (* and the non-repeating part (if it exists) without parentheses *)
   {x__Integer, i___String} :> "" <> {"" <> ToString /@ {x}, i}}}

Tests

h @@@ {{81, 3}, {-81, 3}, {1, 4}, {-13, 3}, {19, 7}, {3289323463, 25000}, {235, 14}, {1325, 14}}

{27, -27, 0,25, -4. (3), 2. (714285), 131572.93852, 16,7 (857142), 94,6 (428571)}

DavidC
quelle