Wdrożenie dowolnego podziału precyzji

15

Zaimplementuj funkcję, divide(int a, int b, int c)która wypisuje podstawową wartość 10 a/b. bez korzystania z matematyki zmiennoprzecinkowej ani BigInteger/ BigDecimallub równoważnych bibliotek. Należy wydrukować co najmniej cdokładne znaki w zestawie 0123456789., z wyjątkiem (możliwego) wyjątku w punkcie 4 poniżej.

  1. ai bmogą być dowolnymi 32-bitowymi liczbami całkowitymi. Aktualizacja: Jeśli do gry w golfa chciałbyś mieć 64-bitowe prymitywy, to jest w porządku, ale nie musisz obsługiwać całego 64-bitowego zakresu danych.
  2. Nie musisz sprawdzać, czy cjest to pozytywne (choć mam nadzieję, że twój program nie ulega awarii), jeśli tak nie jest.
  3. Minimalna obsługiwana górna granica dla cto 500. Jest w porządku, jeśli twój program nie obsługuje wartości cpowyżej 500, ale jest również w porządku, jeśli tak.
  4. W przypadku liczb, które dzielą się równomiernie, wybierasz, czy chcesz wydrukować dodatkowe zera (na podstawie wartości c), czy nic.
  5. Nie musisz być w stanie używać tej funkcji do wykonywania dalszych zadań z ilorazem, jedynym celem jest drukowanie.
  6. W przypadku liczb między -1i od 1Ciebie zależy, czy chcesz wydrukować wiodącą wartość 0. Jest to jednak jedyny scenariusz, w którym drukowanie wiodącego zera jest dopuszczalne i można wydrukować tylko jedno takie zero.
  7. Możesz użyć dowolnej logiki zaokrąglania / podłogi / sufitu dla ostatniego miejsca po przecinku.
  8. W przypadku odpowiedzi negatywnej musisz wydrukować wiodącą -. To się nie liczy c. Jednakże, jest to Twój wybór, jeśli chcesz wydrukować , +lub nic na pozytywną odpowiedź.
  9. Dozwolone są zarówno dzielenie całkowite, jak i moduł całkowity. Pamiętaj jednak, że jesteś ograniczony do prymitywów, chyba że zdecydujesz się zaimplementować własną bibliotekę BigInteger/ BigDecimalbibliotekę, która liczy się do długości twojego kodu.
  10. Nie musisz zajmować się bbytem 0, chociaż możesz, jeśli chcesz. Twój program może wejść w nieskończoną pętlę lub ulec awarii, jeśli b=0nie zostaniesz ukarany.
  11. Niewielka zmiana reguły dla komentarza. Aby upewnić się, że pole gry jest poziom, natomiast ai bsą gwarancją 32-bitowe liczby całkowite, można użyć 64-bitowych długich liczb całkowitych. Jeśli wybrany język wykracza poza 64-bitowe liczby całkowite jako prymityw, nie możesz w żadnym momencie korzystać z tej funkcji (udawać, że jest ograniczony do 64 bitów).
  12. Inna kwestia, która jest niejasna (nie powinna jednak zmieniać żadnej z aktualnych poprawnych odpowiedzi): chociaż cmoże być interpretowana albo jako liczba drukowanych znaków, albo liczba spacji po przecinku, twój program musi cjakoś używać w odpowiedni sposób aby zdecydować, ile znaków do wydrukowania. Innymi słowy, divide(2,3,2)wyjście powinno być znacznie krótsze niż divide(2,3,500); wydrukowanie 500 znaków bez względu na to nie jest w porządku c.
  13. Właściwie nie dbam o nazwę funkcji. djest w porządku do gry w golfa.

Wejście

stdinAkceptowane jest zarówno wywołanie funkcji, jak i odczyt . Jeśli czytasz z stdin, dowolny znak spoza zestawu [-0123456789]jest uważany za separator argumentu.

Wynik

Znaki stdoutjak opisano powyżej.

Przykład

ponieważ divide(2,3,5)wszystkie z poniższych są dopuszczalnymi wynikami:

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

Kolejny przykład: dla divide(371,3,5)następujących są wszystkie dopuszczalne wyniki:

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

I dla divide(371,-3,5)następujących są wszystkie dopuszczalne:

-123.6
-123.7
-123.66666
-123.66667
durron597
źródło
Ze względu na równe szanse rozsądne może być podanie określonej maksymalnej długości bitów, która może być używana (prymitywna lub inna), chyba że utworzysz własną większą implementację, ponieważ a) w niektórych językach długość bitów prymitywów różni się w zależności od podstawowa architektura ib) w niektórych językach typy dużych liczb prymitywne.
Jonathan Van Matre
@JonathanVanMatre Dodano regułę 11 do komentarza
durron597,
1
Jak liczyć dokładne cyfry ? W twoim przykładzie widzę trzy lub cztery, ale nigdy pięć, jak wskazuje ostatni argument.
Howard
@Jak to 92,3,5zrobiłbyś, na przykład,30.67
durron597
1
btw 370/3 = 123,333 lol
izabera

Odpowiedzi:

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

Musiałem improwizować tak, że aalbo bmoże być -2147483648 jako dodatnie 32-bitowe liczby całkowite liczyć tylko w kierunku 2147483647, dlatego astał się long. Może istnieć lepszy sposób radzenia sobie z negatywnymi wynikami, ale nie znam żadnego ( doubleprawdopodobnie zapewnią to działanie, abs(a) < abs(b)ponieważ mają, -0ale tylko dopełnianie jednego z nich zachowa precyzję).

Dlaczego dwie liczby bajtów? Potrzebowałem 92 bajtów do obliczeń i 36 dla pomocnika drukowania (do System.out.printbani; generalnie Java nie jest taka golfowa).

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

Metoda w zasadzie ćwiczy to, czego większość z nas nauczyła się w szkole, aby wygenerować wymagane cyfry dziesiętne.

TheConstructor
źródło
Oficjalne orzeczenie: powiedziałbym, że ignorowanie Integer.MIN_VALUEnie jest w porządku, ale longjako że dane wejściowe są w porządku.
durron597
To o wiele krótsze. Ładnie wykonane.
durron597
@ durron597 dziękuję. Wciąż ścisłe pisanie i System.outsprawia, że ​​Java wydaje się nieporęczna ;-) Nadal dobre wrażenie, że już są dłuższe odpowiedzi.
TheConstructor
1
@ durron597 specjalnie poprosiłeś o funkcję, więc pomyślałem, że się nie liczy. Gdybym musiał użyć importu, prawdopodobnie tak.
TheConstructor
1
Przynajmniej nie ma $ dla każdej zmiennej ;-)
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;}

drukuje ccyfry po.

przykładowe dane wyjściowe:

d(2,3,5);
0.66666

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

d(24352345,31412,500);
775.25611231376543995925124156373360499172290844263338851394371577740990704189481726728638736788488475741754743410161721635043932255189099707118298739335285878008404431427479943970457150133706863618999108620909206672609193938622182605373742518782630841716541449127721889723672481854068508850120972876607665860180822615560932127849229593785814338469374761237743537501591748376416656055010823888959633261174073602444925506175983700496625493441996689163377053355405577486310963962816757926906914554947153953

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

powinien działać dla -2147483647 <= a <= 2147483647, to samo dla b. radzenie sobie z tym -było uciążliwe.

wersja online: ideone

izabera
źródło
Czy to działa na istnienie -2147483648? Nie znam wystarczająco dobrze kompilatorów c, aby stwierdzić, który typ całkowity jest przypisany do parametrów.
TheConstructor
dzięki za zwrócenie na to uwagi. działa poprawnie dla -2147483647 <= a <= 2147483647, to samo dla b. istnieje problem, gdy a = -2147483648 ib jest dodatnia z powodu a=-a.
izabera
Próbowałem, ale w końcu dostałem zasadniczo takie samo rozwiązanie jak ty. Możesz uratować jedną postać, wiedząc, że printf("-")zwraca 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;}

Działa po prostu wyprowadzając iloraz a/ bpodczas pętli ckroków, astając się resztą pomnożoną przez 10 przy każdej iteracji.

PRÓBNY

Razvan
źródło
Daje dziwne wyniki, gdy a lub b są ujemne
TheConstructor
Naprawiłem błąd dla liczb ujemnych. Dzięki!
Razvan
Właśnie znalazłem wersję 112 kodu: 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;}}patrz zwracana wartość
TheConstructor
Dzięki. Zaktualizowałem nawet twoją wersję i udało mi się wygrać dodatkowy 1 bajt.
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]

To rozwiązanie nie narusza żadnej z podanych zasad.

Abhijit
źródło
2

C: 72 znaki

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

Prawie całkowicie robi to, co powinien. Jednak, ponieważ niektóre inne odpowiedzi tutaj przyniosą dziwne wartości lub zawiodąd(-2147483648,b,c) a d(a,-2147483648,c)ponieważ wartość bezwzględna -2147483648 jest poza zakresem dla słowa 32-bitowego.

Fors
źródło
2

Perl, brak arytmetyki, 274 bajty

Jest to długi podział euklidesowy , który prawdopodobnie pochłonie niezwykłą ilość pamięci. Najbliżej matematyki na liczbach zmiennoprzecinkowych jest użycie operacji bitowych do ich analizy.

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

Przykłady:

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

Wynik:

-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
użytkownik130144
źródło
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

Wersja online do testowania.

Sztuczka polega na pomnożeniu a przez dość dużą liczbę, więc wynikiem jest tylko liczba całkowita operacji zmiennoprzecinkowej. Następnie punkt i zera należy wstawić we właściwym miejscu w wynikowym ciągu.

David Herrmann
źródło
Czy to działa dla c większego niż 350?
durron597,
Przetestowałem to z c = 1000 - kod dał mi odpowiedź, może powinienem jednak sprawdzić rzeczywisty wynik ...
David Herrmann
2
ma gwyjść poza 64 bitów dla dużych c? Edycja: Myślę, że domyślnie używasz BigIntegertutaj
durron597
Err, gto ciąg znaków, ale zanim zadzwonisz to_s, utworzyłeś w pamięci liczbę przekraczającą 64 bity
durron597
1
Jest to zrozumiałe - i sprawia, że ​​zadanie jest trudniejsze (i interesujące)! Czy lepiej jest usunąć odpowiedź, czy pozostawić ją innym, aby miała przykład tego, jak nie wykonać zadania?
David Herrmann
1

python 92 bajty:

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

myślę, że możliwe jest trochę golfa .....

Maltysen
źródło
2
robi ewięcej niż 64 bity dla dużego c? Edycja: Myślę, że domyślnie używasz BigIntegertutaj.
durron597
1
@ durron597 bardzo w to wątpię. Idzie do BigInt (Long in python), ale 2 ** 45 to 48 bitów. Czy to wystarczy presicion? Także python NIE ma prymitywów, więc ...
Maltysen
Jeśli a=5i c=400to po e=10**c, w hex, numer jest 333 cyfr. Zaczyna się, 8889e7dd7f43fc2f7900bc2eac756d1c4927a5b8e56bbcfc97d39bac6936e648180f47d1396bc905a47cc481617c7...że jest to więcej niż 64 bity.
durron597
@ durron597 400 ... czy potrzebuję tego
Maltysen
1
Tak, reguła 3 mówi, że musisz wesprzeć co najmniej 500 ... Próbowałem zapobiec temu (imo trywialnemu) rozwiązaniu.
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);}

Ten sam pomysł, którego użyłem w mojej implementacji Python

Abhijit
źródło
Bardzo dobrze! Jednak zawiesza sięd(-2147483648,-1,10)
durron597