Implémenter une division de précision arbitraire

15

Implémentez une fonction divide(int a, int b, int c)qui imprime la valeur de base 10 de a/b. sans utiliser de mathématiques en virgule flottante ni BigInteger/ BigDecimalou de bibliothèques équivalentes. Au moins cdes caractères précis dans l'ensemble de 0123456789.doivent être imprimés, à l'exception de l'exception (possible) du point 4 ci-dessous.

  1. aet bpeut être n'importe quel entier 32 bits. Mise à jour: si, à des fins de golf, vous souhaitez que les entrées soient des primitives 64 bits, cela est correct, mais vous n'avez pas besoin de prendre en charge toute la plage de données 64 bits.
  2. Vous n'avez pas besoin de vérifier que cc'est positif (bien que nous espérons que votre programme ne plante pas) si ce n'est pas le cas.
  3. La borne supérieure minimale prise en charge pour cest 500. Ce n'est pas grave si votre programme ne prend pas en charge les valeurs cci 500- dessus , mais c'est également correct si c'est le cas.
  4. Pour les nombres qui se divisent uniformément, vous avez le choix d'imprimer des zéros supplémentaires (basés sur la valeur de c) ou rien.
  5. Vous n'avez pas besoin de pouvoir utiliser la fonction pour effectuer d'autres tâches avec le quotient, le seul objectif est l'impression.
  6. Pour les nombres entre -1et 1, vous avez le choix d'imprimer ou non un interligne 0. Cependant, c'est le seul scénario où l'impression d'un zéro de tête est acceptable et vous ne pouvez imprimer qu'un seul de ces zéro.
  7. Vous pouvez utiliser n'importe quelle logique d'arrondi / plancher / plafond que vous préférez pour la dernière décimale.
  8. Pour une réponse négative, vous devez imprimer un interligne -. Cela ne compte pas c. Cependant, il est de votre choix si vous souhaitez imprimer , +ou rien pour une réponse positive.
  9. La division entière et le module entier sont tous deux autorisés. Cependant, gardez à l'esprit que vous êtes limité aux primitives, à moins que vous ne choisissiez d'implémenter votre propre BigInteger/ BigDecimalbibliothèque qui compte contre votre longueur de code.
  10. Vous n'avez pas besoin de gérer l' bêtre 0, bien que vous puissiez le faire si vous le souhaitez. Votre programme peut entrer dans une boucle infinie, ou se bloquer, si b=0, et vous ne serez pas pénalisé.
  11. Léger changement de règle par commentaire. Pour vous assurer que le terrain de jeu est de niveau, alors que aet bsont garantis comme étant des entiers 32 bits, vous pouvez utiliser des entiers longs 64 bits. Si votre langue choisie va au-delà des entiers 64 bits en tant que primitive, vous ne pouvez à aucun moment utiliser cette fonctionnalité (prétendre qu'elle est limitée à 64 bits).
  12. Un autre point qui n'est pas clair (cependant, cela ne devrait changer aucune des réponses valides actuelles): bien qu'il cpuisse être interprété comme le nombre de caractères imprimés ou le nombre d'espaces après la décimale, votre programme doit utiliser cd'une manière pertinente d'une manière pertinente pour décider du nombre de caractères à imprimer. En d'autres termes, la divide(2,3,2)sortie devrait être beaucoup plus courte que divide(2,3,500); il n'est pas correct d'imprimer 500 caractères sans tenir compte de c.
  13. En fait, je me fiche du nom de la fonction. dest correct pour le golf.

Contribution

Un appel de fonction et une lecture stdinsont acceptés. Si vous lisez stdin, tout caractère ne figurant pas dans l'ensemble [-0123456789]est considéré comme un délimiteur d'argument.

Production

Caractères stdoutcomme décrit ci-dessus.

Exemple

pour divide(2,3,5), toutes les sorties suivantes sont acceptables:

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

Un autre exemple: pour divide(371,3,5)ce qui suit sont toutes les sorties acceptables:

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

Et pour divide(371,-3,5)ce qui suit sont tous acceptables:

-123.6
-123.7
-123.66666
-123.66667
durron597
la source
Par souci d'équité, il pourrait être judicieux de donner une longueur de bit maximale spécifique qui peut être utilisée (primitive ou autre) à moins que vous ne rouliez votre propre implémentation plus grande, car a) dans certaines langues, la longueur de bit des primitives varie en fonction de l'architecture sous-jacente et b) dans certains langages, les types de grands nombres sont des primitives.
Jonathan Van Matre
@JonathanVanMatre Ajouté la règle 11 par votre commentaire
durron597
1
Comment comptez-vous les chiffres précis ? Dans votre exemple, j'en vois trois ou quatre mais jamais cinq comme l'indique le dernier argument.
Howard
@Howard, si vous l'avez fait, 92,3,5la réponse serait, par exemple,30.67
durron597
1
btw 370/3 = 123,333 lol
izabera

Réponses:

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

J'ai dû improviser pour que aou bpuisse être -2147483648 car les entiers 32 bits positifs ne comptent que pour 2147483647, c'est pourquoi aest devenu un long. Il pourrait y avoir une meilleure façon de gérer les résultats négatifs, mais je n'en connais aucun (il doubleest probable que cela fonctionnera abs(a) < abs(b)comme ils l'ont fait, -0mais seul le complément conservera la précision).

Pourquoi deux nombres d'octets? J'avais besoin de 92 octets pour le calcul et de 36 pour l'assistant d'impression ( System.out.printça craint; généralement Java n'est pas si golfique).

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

La méthode utilise essentiellement ce que la plupart d'entre nous avons appris à l'école pour générer les chiffres décimaux demandés.

TheConstructor
la source
Décision officielle: je dirais que l'ignorance Integer.MIN_VALUEn'est pas acceptable, mais qu'en longtant qu'entrée, c'est bien.
durron597
C'est beaucoup plus court. Bien fait.
durron597
@ durron597 merci. Toujours la frappe stricte et System.outrend Java volumineux ;-) Toujours un bon sentiment, qu'il existe déjà des réponses plus longues.
TheConstructor
1
@ durron597 vous avez spécifiquement demandé une fonction donc j'ai pensé qu'elle ne compterait pas. Si je devais utiliser des importations, probablement oui.
TheConstructor
1
Au moins, il n'y a pas de $ pour chaque 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;}

imprime des cchiffres après.

exemple de sortie:

d(2,3,5);
0.66666

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

d(24352345,31412,500);
775.25611231376543995925124156373360499172290844263338851394371577740990704189481726728638736788488475741754743410161721635043932255189099707118298739335285878008404431427479943970457150133706863618999108620909206672609193938622182605373742518782630841716541449127721889723672481854068508850120972876607665860180822615560932127849229593785814338469374761237743537501591748376416656055010823888959633261174073602444925506175983700496625493441996689163377053355405577486310963962816757926906914554947153953

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

devrait fonctionner pour -2147483647 <= a <= 2147483647, idem pour b. manipuler le -était une douleur.

version en ligne: ideone

izabera
la source
Est-ce que cela fonctionne pour un être -2147483648? Je ne connais pas assez bien les compilateurs c pour savoir quel type d'entier est affecté à vos paramètres.
TheConstructor
merci de l'avoir signalé. cela fonctionne correctement pour -2147483647 <= a <= 2147483647, idem pour b. il y a un problème lorsque a = -2147483648 et b est positif en raison de a=-a.
izabera
J'ai essayé mais j'ai finalement obtenu essentiellement la même solution que vous. Vous pouvez enregistrer un personnage en réalisant que printf("-")renvoie 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;}

Il fonctionne simplement en sortant le quotient de a/ bpendant une boucle d' cétapes, adevenant le reste multiplié par 10 à chaque itération.

DEMO

Razvan
la source
Produit des résultats étranges lorsque a ou b sont négatifs
TheConstructor
J'ai corrigé le bogue pour les nombres négatifs. Merci!
Razvan
Je viens de trouver une version 112 de votre code: 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;}}voir valeur de retour
TheConstructor
Merci. J'ai même mis à jour votre version et j'ai réussi à gagner un octet supplémentaire.
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]

Cette solution ne viole aucune des règles énoncées.

Abhijit
la source
2

C: 72 caractères

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

Il fait presque entièrement ce qu'il est censé faire. Cependant, comme certaines des autres réponses ici donneront des valeurs bancales ou échoueront d(-2147483648,b,c)et d(a,-2147483648,c)puisque la valeur absolue de -2147483648 est hors limites pour un mot de 32 bits.

Fors
la source
2

Perl, pas d'arithmétique, 274 octets

Il s'agit d'une longue division euclidienne , susceptible de consommer une quantité inhabituelle de mémoire. Le plus proche des mathématiques sur les nombres à virgule flottante est d'utiliser des opérations binaires pour les analyser.

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

Exemples:

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

Production:

-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
user130144
la source
1

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

Version en ligne pour les tests.

L'astuce consiste à multiplier un par un nombre assez élevé, donc le résultat n'est qu'un multiple entier de l'opération à virgule flottante. Ensuite, le point et les zéros doivent être insérés au bon endroit dans la chaîne résultante.

David Herrmann
la source
Est-ce que cela fonctionne pour c supérieur à 350?
durron597
Je l'ai testé avec c = 1000 - le code m'a donné une réponse, peut-être que je devrais vérifier le résultat réel ...
David Herrmann
2
va gau-delà de 64 bits pour les grands c? Edit: Je pense que vous utilisez implicitement BigIntegerici
durron597
Err, gest une chaîne, mais avant d'appeler, to_svous avez créé un numéro en mémoire d'une taille supérieure à 64 bits
durron597
1
Cela est compréhensible - et rend la tâche plus difficile (et intéressante)! Est-il préférable de supprimer la réponse ou de laisser aux autres un exemple de la façon de ne pas mettre en œuvre la tâche?
David Herrmann
1

python 92 octets:

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

je pense que plus de golf est possible .....

Maltysen
la source
2
va eau-delà de 64 bits pour les grands c? Edit: Je pense que vous utilisez implicitement BigIntegerici.
durron597
1
@ durron597 j'en doute fortement. Il va à BigInt (Long en python) mais 2 ** 45 est de 48 bits. Est-ce que cela suffit? De plus, python n'a AUCUNE primitive donc ...
Maltysen
Si a=5et c=400ensuite après e=10**c, en hexadécimal, le nombre comporte 333 chiffres. Il démarre 8889e7dd7f43fc2f7900bc2eac756d1c4927a5b8e56bbcfc97d39bac6936e648180f47d1396bc905a47cc481617c7...c'est plus de 64 bits.
durron597
@ durron597 400 ... ai-je besoin de ça
Maltysen
1
Oui, la règle 3 dit que vous devez prendre en charge au moins 500 ... J'essayais d'empêcher cette solution (imo triviale).
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);}

Même idée que j'ai utilisée dans mon implémentation python

Abhijit
la source
Très agréable! Cependant, il se bloqued(-2147483648,-1,10)
durron597