Niech rozpocznie się trygonometria!


20

Wprowadzenie:

Sinus z xwyraża się wzorem:

sin(x) = x - x^3/3! + x^5/5! - x^7/7! + x^9/9! - x^11/11! // and more follows...

Cosinus z xoblicza się według wzoru:

cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8! - x^10/10! // and more follows...

Zadanie:

Biorąc pod uwagę wartość xi n, napisz program (bez funkcji itp.), Aby wypisał wartość sin(x)i cos(x)poprawił upto nwarunki powyższej formuły. Załóżmy, że xjest w radianach.

Wejście:

x n

Liczba dziesiętna x(z maksymalnie 3 miejscami dziesiętnymi) i liczba całkowita n. Dane wejściowe muszą być ustawione na standardowe wejście lub okno dialogowe z pytaniem (jeśli Twój język nie obsługuje standardowego wejścia)

Wynik:

[sin(x)]
[cos(x)]

Wartość obu sin(x)i cos(x)powinny być zaokrąglone do 6 miejsc po przecinku. Jeśli sin(x)jest 0.5588558855(10 cyfr dziesiętnych), należy je zaokrąglić do 0.558856(6 cyfr dziesiętnych). Zaokrąglanie musi odbywać się do najbliższej, jak opisano w piątej kolumnie „Zaokrąglaj do najbliższej” tabeli w tym artykule Wiki .

Ograniczenia:

1 <= x <= 20
1 <= n <= 20

Próbki:

----
5 3

10.208333
14.541667
----
8.555 13

0.765431
-0.641092
----
9.26 10

-3.154677
-8.404354
----
6.54 12

0.253986
0.967147
----
5 1

5.000000
1.000000
----
20 20

-5364.411846
-10898.499385
----

Uwagi:

  1. Standardowe luki są zabronione.
  2. Wbudowane funkcje matematyczne i operatory trygonometrii (sin, cos, tan itp.), Silnia i potęgowanie nie mogą być używane. Możesz użyć wbudowanej funkcji zaokrąglania do oszacowania wyniku obliczeń sin(x)i cos(x)do 6-tej cyfry dziesiętnej.
  3. Nie ma potrzeby obsługi niewłaściwych danych wejściowych.
  4. W programie można używać tylko znaków ASCII, a nie chińskich znaków Unicode, które umożliwiają kompresję kodu.
  5. Twój program musi zakończyć działanie i wyświetlić dane wyjściowe w ciągu 3 sekund od wejścia.
  6. Twoja odpowiedź musi towarzyszyć niepoddanemu kodowi wraz z objaśnieniem kodu (obowiązkowe, jeśli kod nie jest od razu oczywisty dla programistów, którzy nie znają Twojego języka, zwłaszcza GolfScript, J itp.).
  7. Podaj link do kompilatora online, w którym można przetestować Twój program.

Punktacja:

Odpowiedź z najniższą długością kodu w znakach, w tym spacjami, tabulatorami itp. Wygrywa! Zwycięzca zostanie ogłoszony 21 maja 2014 r.

EDYCJA : 21.05.14 Zwycięzca jest aditsu w języku CJam . Drugie miejsce następujące jpjacobs z językiem J , a po drugie drugie miejsce jest Primo z językiem Perl . Gratulacje dla wszystkich!


(Mod uwaga: komentarze nuked Proszę ping mnie za jakiekolwiek utracone informacje, które mogłyby chcesz; wygląda jak po moim ostrzeżeniu z góry, wszystko trafiła do kwestii chociaż.).
klamce

W pierwszym akapicie powinno to być „sinusoida”, a nie „grzech”
nie to, że Karol

Czy „Zaokrąglanie do najbliższego” nadal jest wymogiem, czy też możemy korzystać z wbudowanych funkcji zaokrąglania? np. zaokrąglić w kierunku zera?
Cyfrowa trauma

Wymaganie odpowiednika mod 2pioperacji w celu przyspieszenia konwergencji danych wejściowych byłoby raczej przydatne - jest to jedna z wielu ulepszeń, z których korzysta świat rzeczywisty podczas obsługi tych funkcji. (właściwie mod pi i znak świadomości).
Floris

1
@Floris Nigdy tego nie wiedziałem. Cóż, nie możemy teraz nic zrobić, reguły już się wiele zmieniły i nie chcę ich ciągle zmieniać, aby jeszcze bardziej irytować osoby odpowiadające. Dziękuję za sugestię!
Gaurang Tandon

Odpowiedzi:


6

CJam - 42

rd:X;1_ri2*,1>{_2%2*(*/X*_}/;]2/z{:+6mO}/p

Wypróbuj online pod adresem http://cjam.aditsu.net

Wyjaśnienie:

rodczytuje token z danych wejściowych
dkonwertuje na podwójne
:Xprzypisania do zmiennej X
;wyskakuje wartość ze stosu
1umieszcza 1 na stosie (pierwszy termin)
_duplikuje 1
rczyta następny token (n)
ikonwertuje na liczbę całkowitą
2*,1>{...}/jest rodzajem pętli z 1 do 2 * n - 1:
- 2*mnoży przez 2
- ,tworzy tablicę od 0 do (ostatnia wartość) -1
- 1>usuwa pierwszy element tablicy (0)
- {...}/wykonuje blok dla każdego elementu w tablicy
_powiela pętlę „ zmienna "(nazwijmy to k)
2%2*(konwertuje z parzystej / nieparzystej na -1/1:
- 2%jest modulo 2 (-> 0/1)
- 2*mnoży przez 2 (-> 0/2)
-(zmniejszenie (-> -1/1)
*mnoży się, zmieniając znak co drugi raz,
/dzieląc termin na stosie przez k lub -k; to jest „/ k!” część obliczeń wraz ze zmianą znaku
X*mnoży się przez X; jest to część obliczeń „X ^ k”; uzyskaliśmy kolejny termin z serii
_duplikatów termin, który będzie używany do obliczenia następnego terminu w następnej iteracji
;(po pętli) wyskakuje ostatni zduplikowany termin
]zbiera warunki na stosie w tablicy
W tym momencie mamy tablicę [ 1 X -X ^ 2/2! -X ^ 3/3! X ^ 4/4! X ^ 5/5! ...] zawierające dokładnie wszystkie terminy, których potrzebujemy dla cos (x) i sin (x), przeplatane
2/dzieli tę tablicę na pary
ztransponuje macierz, uzyskując tablicę z terminami dla cos (x) i tablicę z terminami sin (x), ponieważ „rzędy macierzy”
{...}/ponownie wykonują blok dla każdego elementu tablicy (wiersz macierzy):
- :+dodaje elementy rzędu macierzy razem
- 6mOzaokrągla do 6 miejsc po przecinku
W tym momencie mamy pożądane cos (x), a sin (x) na stosie
pdrukuje reprezentację ostatniego elementu na stosie (sin (x)), po którym następuje nowa linia
At na końcu programu pozostała zawartość stosu (cos (x)) jest drukowana automatycznie.


1
+1 za wprowadzenie mnie w język, o którym nigdy nie słyszałem i prawdopodobnie nigdy go nie użyję.
Alex A.,

@Alex dzięki, CJam jest trochę jak GolfScript na sterydach
aditsu

Nie lubię zmieniać reguł po opublikowaniu pytania, ale nie zezwalam na znaki zezwalające na kompresję kodu Unicode, ponieważ nie wiedziałem, że znaki Unicode mogą być używane do kompresji kodu. Teraz można używać tylko znaków ASCII. Edytuj swój post. Przepraszamy za niedogodności.
Gaurang Tandon

@GaurangTandon Też mi się nie podoba. Jak myślisz, do czego jeszcze można by użyć chińskich znaków w tym problemie? W każdym razie edytowane.
aditsu

18

Perl - 72 bajty

$~=<>=~$"+$'*2;$_=1-$_*$`/$~--/$~*$`for($,,$;)x$';printf'%f
%f',$`*$,,$;

Lub licząc opcje wiersza poleceń jako 1 bajt każdy, w 70 bajtach :

#!perl -n
$-=/ /+$'*2;$_=1-$_*$`/$---/$-*$`for($,,$;)x$';printf'%f
%f',$`*$,,$;

Lub, jeśli pozwolisz mi Perl 5.8, w 63 bajtach :

#!perl -p
$.+=$'<</ /;$_=1-$_*$`/$.--/$.*$`for($_=$#='%f
',$\)x$';$_*=$`

ale dlaczego miałbyś

Edycja : zgodność z nowymi regułami. %fzaokrągla domyślnie do 6 miejsc, jakie to wygodne!


Algorytm

Badanie serii Taylora pod kątem grzechu (x) :

można zauważyć, że każdy termin równomiernie dzieli każdy kolejny termin. Z tego powodu można go bez trudu przekształcić w wyrażenie zagnieżdżone:

cos (x) przekształca się podobnie, bez wiodącego x , a mianownik jest o jeden mniejszy.

Dodatkowo to zagnieżdżone wyrażenie może zostać przeformułowane jako odwrotne wyrażenie rekurencyjne:

ze s = 0 i sin (x) = x · s 1 , który jest ostatecznie używany.


Nie golfił

<> =~ m/ /;          # read one line from stdin, match a space
                     # prematch ($`) is now x, postmatch ($') is now n
($x, $n) = ($`, $'); # reassign, for clarity
$i = 2*$n + 1;       # counting variable (denominators)

for (($s, $c)x$n) {  # iterate over $s and $c, n times each
  # compute the next term of the recursive expression
  # note: inside this loop $_ is not the _value_
  # of $s and $c alternately, it _is_ $s and $c

  $_ = 1 - $_ * $x**2 / $i-- / $i;
}

# formated output
printf("%f\n%f", $x*$s, $c);

Przykładowe użycie

$ echo 5 3 | perl sin-cos.pl
10.208333
14.541667

$ echo 8.555 13 | perl sin-cos.pl
0.765431
-0.641092

$ echo 9.26 10 | perl sin-cos.pl
-3.154677
-8.404354

$ echo 6.54 12 | perl sin-cos.pl
0.253986
0.967147

$ echo 5 1 | perl sin-cos.pl
5.000000
1.000000

$ echo 20 20 | perl sin-cos.pl
-5364.411846
-10898.499385

Jeśli chcesz to przetestować online, polecam korzystanie z compileonline.com . Skopiuj i wklej kod main.pl, a następnie dane wejściowe w STDINpolu Execute Script.


2
Jaki przebiegły sposób na przeanalizowanie danych wejściowych ... czy mogę tego użyć w swoim rozwiązaniu? :)
Tal

@Tal Zapraszam.
primo

2
Myślę, że perl (a zwłaszcza twój kod) liczy się jako „nie od razu oczywisty dla programistów, którzy nie znają twojego języka”
aditsu

1
@aditsu uzgodnione. Dodam trochę czystszego kodu i wyjaśnienie algorytmu.
primo

2
Ta odpowiedź była naprawdę bardzo pouczająca!
Tal

10

Python 3 (102) / Python 2 (104)

Python 3 (102)

x,n=map(float,input().split())
k=2*n
t=1
while k>1:k-=1;t=1+t*1j*x/k
print('%.6f\n'*2%(t.imag,t.real))

Python 2.7 (104)

x,n=map(float,raw_input().split())
k=2*n
t=1
while k>1:k-=1;t=1+t*1j*x/k
print'%.6f\n'*2%(t.imag,t.real)

Zasadniczo ten sam kod. Oszczędzamy dwie postacie przed niepotrzebnymi parenami, printale tracimy cztery z potrzeby raw_input.

Przykładowy przebieg

Możesz je uruchomić tutaj .

>>>
20 20
-5364.411846
-10898.499385

Wyjaśnienie kodu

Główną ideą jest obliczenie 2*nwarunków e^(ix), a następnie wzięcie części wyobrażonej i rzeczywistej, aby uzyskać wartości sini cosprzybliżone do nwarunków. Używamy skrótu z serii Taylor:

e^(ix)≈sum_{k=0}^{2n-1} (i*x)^k/k!

Jest to wielomian w i * x, ale zamiast obliczać jego wartość sumując każdy termin, używamy zmodyfikowanej metody Hornera do obliczania sekwencji (zdefiniowanej rekurencyjnie w odwrotnej kolejności)

t_{2n} = 1
t_k = 1 + t_{k+1}*i*x/k,

co daje t_1wyrównanie pożądanej wartości.

Operacje formatowania napisów w języku Python służą do wyświetlania wartości w zaokrągleniu do 6 cyfr dziesiętnych.

Edycja: zmieniono na okrągłe do 6 cyfr zgodnie z nowymi zasadami. Żadne inne zmiany nie były potrzebne.


Wypróbuj ideone dla internetowego tłumacza py3 :)
Harry Beadle

@BritishColour Thanks! Dodałem go do postu.
xnor

Zaktualizuj swoją odpowiedź. Zobacz szczegóły w pytaniu. Dzięki.
Gaurang Tandon

8

J 98 70 69 58

Chociaż można to prawdopodobnie nieco skrócić, używając bardziej fantazyjnych funkcji ... komentarze są mile widziane:

exit echo 0j6":,.-/(($%&(*/)1+i.@[)"0~i.@,&_2)/".}:stdin''

Uwaga 2: Wejście kończy się po otrzymaniu EOF (Ctrl-D w Linuksie). Edycja: połączyć potęgowanie oraz silnia w ładniejszy, bardziej J ish całości: ($ %&(*/) >:@i.@[ ). Sprowadza się to do pobrania tablicy x replikacji yi tablicy liczb od 1 do y. Pomnóż każdy i podziel wynik. Pozbywa się duplikatu */.

Dzięki algortihmshark kolejne 7 znaków jest wyłączone.

Wyeliminowano cięcie, aby pozbyć się nowej linii.

Dłuższa wersja, dla której niezbędna jest znajomość widelców.

NB. recursive Factorial
f=: */@>:@i.      NB. multiply all from 1 to n
NB. Exponential
e=: */@$          NB. replicate y x times, take the product.
NB. the x t y is the Nth (general) term without sign of the joint series
t=: (e % f@[)"0  NB. pretty straight forward: divide by (x!) on the exponential

NB. Piece the parts together, from right to left:
NB. read from stdin, cut the linefeed off , make the 2 n terms in 2 columns, which
NB. effectively splits out pair and odd terms, put in the minuses, put in rows
NB. instead of columns, echo, exit
exit echo 0j6&": ,. (-/) (i.@(,&_2)@{: t {.) , (". ;. _2) stdin''

Nie ma internetowego tłumacza języka J, ale jest to oprogramowanie typu open source od kilku lat; instalacja jest łatwa dzięki następującym instrukcjom:

http://www.jsoftware.com/jwiki/System/Installation/J801

Na #jsoftware na irc.freenode.org jest też bot J.

stdin działa tylko wtedy, gdy wybiegł z pliku, z linii poleceń, jeszcze wymienić stdin ''z 'a b;'gdzie aib to numery, które zostały przekazane na polecenia.


5
Uwielbiam to, że zaczyna się odexit
Digital Trauma

Zaktualizuj swoją odpowiedź. Zobacz szczegóły w pytaniu. Dzięki.
Gaurang Tandon

Zaktualizowano dla 6 miejsc po przecinku. Jeśli jest coś jeszcze, proszę podać. Dzięki
jpjacobs

Możesz usunąć &z, 0j6&":aby zapisać znak. Ponadto, (i.@(,&_2)@{:($%&(*/)>:@i.@[)"0{.)mogą być zapisane (($%&(*/)1+i.@[)"0~i.@,&_2)/na innym 6.
algorithmshark

Zadanie to krzyczy T.(przybliżona funkcja według n-termicznej serii Taylora), ale myślę, że to słowo werbalne jako standardowa luka.
FUZxxl

6

Perl, 120 108 104 89 85

<>=~/ /;$c=$t=1;for(1..2*$'-1){$t*=$`/$_;$_%2?$s:$c+=$_&2?-$t:$t}printf"%f\n"x2,$s,$c

Nie golfowany:

<> =~ / /;
$cosine = $t = 1;
for (1.. 2*$' - 1){
  $t *= $` / $_;
  ($_%2 ? $sine : $cosine) += $_&2?-$t:$t
}
printf "%.6f\n" x2, $sine, $cosine

Pierwszy wiersz odczytuje dane wejściowe i używa wyrażenia regularnego, aby znaleźć spację; to automatycznie umieszcza wartość przed spacją w $ `i wartość po niej w $ '.

Teraz zapętlamy od 1 do 2*n-1. $tjest naszym terminem, który pętla wielokrotnie mnoży xi dzieli przez indeks pętli ( $_). Pętla rozpoczyna się od 1 zamiast 0, ponieważ cosinus jest inicjowany na 1, co pozwoliło mi uniknąć dzielenia przez zero.

Po aktualizacji $toperator trójkowy zwraca albo, $sinealbo $cosine, w zależności od tego, czy indeks jest nieparzysty czy parzysty, i dodaje $tdo niego wartość. Magiczna formuła $_&2?-$t:$tmówi, czy dodać lub odjąć tę wartość (w zasadzie używając bitowego - i na indeksie i 2, aby wygenerować powtarzającą się sekwencję „dodawaj, dodawaj, odejmuj, odejmuj”).

Możesz przetestować ten kod na stronie compileonline.com .


Popraw swoje dane wyjściowe dla 20 20.
Gaurang Tandon

1
Myślę, że 1..$n*2-1zamiast tego może być konieczne skorzystanie z pętli for 1..$n. Podczas gdy tu jestem ... $sjest całkowicie w porządku, niezainicjowany, jak undefocenia się 0w kontekście liczbowym. Trójargumentowy zadanie nie wymaga nawiasów: $_&1?$s:$c+=$t. "%.8f\n%.8f"można skrócić do "%.8f\n"x2, w wyniku dodania końcowego nowego wiersza.
primo

@Primo Dzięki, nie wiedziałem o niektórych z nich. A teraz daje nawet poprawny wynik.
Tal

@ Talk Moja przyjemność. Również nieco lepsza magia: $t*(1-($_&2))=> $_&2?-$t:$t.
primo

Zaktualizuj swoją odpowiedź. Zobacz szczegóły w pytaniu. Dzięki.
Gaurang Tandon

5

Fortran: 89 109 125 102 101 98 bajtów

complex*16::t=1;read*,x,n;do k=2*n-1,1,-1;t=1+t*(0,1)*x/k;enddo;print'(f0.6)',aimag(t),real(t);end

Nadużywam niejawnego pisania, ale niestety nie istnieje żaden taki niejawny złożony typ, więc musiałem podać to i kompleks i. Gfortran naturalnie zmniejsza wydajność w 8 miejscach po przecinku, więc jesteśmy dobrzy w tej specyfikacji. Niestety, moja oryginalna metoda wyjściowa print*,tnie spełniała specyfikacji, więc musiałem dodać 16 znaków, aby uzyskać wyimaginowane i rzeczywiste komponenty i uzyskać wymagane 8 miejsc po przecinku.

Dzięki Ventero udało mi się zaoszczędzić 23 bajty między wyjściem a pętlą. I kolejny znak, aby uzyskać poprawne odpowiedzi i sformatowane wyjście. I jeszcze 3 na readwyciągu.

Bez golfa,

complex*16::t=1
read*,x,n
do k=2*n-1,1,-1
   t=1+t*(0,1)*x/k
enddo
print'(f0.6)',aimag(t),real(t)
end

Zaktualizuj swoją odpowiedź. Zobacz szczegóły w pytaniu. Dzięki!
Gaurang Tandon

1
@GaurangTandon: Prawdopodobnie powinieneś przestać zmieniać szczegóły problemu.
Kyle Kanos

Wiem i nie chcę, ale nic na to nie poradzę. W rzeczywistości, po przetestowaniu 5 odpowiedzi, okazało się, że prawie wszystkie z nich dawały różne wyniki (to było rzeczywiście zupełnie nieoczekiwane). Mogłem zastosować inne podejście, ale wymagałoby to całkowitej zmiany algorytmów obecnych odpowiedzi. Ten jest najlepszy, jaki mogłem wymyślić.
Gaurang Tandon

2
Wiem, że mój działa idealnie, więc powinienem całkowicie sprawdzić: D;)
Kyle Kanos

4

C 120

double s,c,r,x;main(i,n){for(scanf("%lf %d",&x,&n),r=1;i<n*2;s+=r,r*=-x/i++)c+=r,r*=x/i++;printf("%.8lf\n%.8lf\n",s,c);}

Aby zapisać bajt, instrukcje aktualizujące wartość sinusoidalną są umieszczane wewnątrz for()instrukcji, ale w rzeczywistości są wykonywane po instrukcjach następujących po nawiasie zamykającym, który aktualizuje wartość cosinusową. (Chyba mógłbym również zaoszczędzić kilka bajtów, usuwając końcowy znak nowej linii w danych wyjściowych programu).

Zmienne globalne s, c, ri xsą niejawnie inicjowany do zera, i ibędzie miał wartość 1 tak długo, jak nie ma argumentów przedstawionych w wierszu poleceń. Niestety printf()domyślnie jest to 6 miejsc po przecinku, więc format wyjściowy jest nieco wyczerpujący.

Nie golfowany:

Oto kod z niewielkimi zmianami, aby porządek, w którym wszystko zostało zrobione, był nieco wyraźniejszy:

double s,c,r,x;
main(i,n) {
    scanf("%lf %d",&x,&n);
    r=1;
    for(;i<n*2;) {
        c+=r;
        r*=x/i++;
        s+=r;
        r*=-x/i++;
    }
    printf("%.8lf\n%.8lf\n",s,c);
}

Przykładowe dane wyjściowe:

$ echo 1.23 4 | ./sincos
0.94247129
0.33410995

Wypróbuj online:

http://ideone.com/URZWwo


3

Python> = 2.7.3, 186 184 211 200 182 170 znaków

Trochę jak diabli. Używa wzoru z pytania sparametryzowanego dla sinusa i cosinusa.

Tłumacz online można znaleźć tutaj tutaj

x,n=map(eval,raw_input().split())
f=lambda n:n<2and 1or n*f(n-1.)
for i in[1,0]:print"%.6f"%sum((1-j%2*2)*reduce(lambda o,p:o*p,[x]*(i+2*j),1)/f(i+2*j)for j in range(n))

Edycja: Ważna wersja ze wszystkimi ograniczeniami

Edycja2: Zmieniono interpreter online na ideone.com z powodu nieprawidłowego rounddziałania funkcji w Pythonie 2.7.1

Edycja3: Okazało się, że użyłem niepotrzebnej inline lambda + zmieniłem zaokrąglanie na format ciągu (skradziony z xnor :))

Edit4: Zastąpiony niedziałającąjoin główną forpętlą


Witajcie, niedawno edytowałem reguły, które teraz nie pozwalają wbudowanym operatorom na potęgowanie (tak **sądzę). Myślę więc, że będziesz musiał zredagować swoją odpowiedź. Przepraszamy za niedogodności. Proszę, popraw mnie jeśli się mylę.
Gaurang Tandon

1
Sądzę, że dalsze modyfikacje są bezużyteczne w odpowiedzi xnora :)
avall

@avail On 20 20, otrzymuję dane wyjściowe -5364.4118142500001. Może chcę to naprawić do 8 miejsc po przecinku.
Gaurang Tandon

Wynika to z wersji repl.it Python 2.7.1. Jeśli uruchomisz go na ideone.com (Python 2.7.3), działa poprawnie. ideone.com/JsYNNK
avall

Teraz działa dobrze! +1
Gaurang Tandon

3

JavaScript - 114 znaków

y=(z=prompt)().split(' ');for(x=l=s=+y[0],c=d=1;--y[1];c+=l*=-x/++d,s+=l*=x/++d);z(s.toFixed(6)+'\n'+c.toFixed(6))

Na podstawie świetnej odpowiedzi Jamesa. Ten sam algorytm, z pominięciem pierwszego kroku przy inicjalizacji c = 1 is = x. Użycie 2 zmiennych zamiast tablicy dla danych wyjściowych upraszcza pętlę.

Nie golfił

y = ( z = prompt)().split(' ');
for ( 
    x = l = s = +y[0], /* init to value x, note the plus sign to convert from string to number */
    c = d = 1;
    --y[1]; /* No loop variable, just decrement counter */
    c += (l *= -x / ++d), /* Change sign of multiplier on each loop */
    s += (l *= x / ++d) 
); /* for body is empty */
z(s.toFixed(6) + '\n' + c.toFixed(6))     

Drobne literówki: Byłoby, s += (l *= x / ++d)a nie s += (l* = x / ++d)w nie golfowym kodzie.
Gaurang Tandon

1
@GaurangTandon naprawiony
edc65

2

JavaScript (wersja robocza ECMAScript 6) - 97 96 znaków

Rozwiązanie rekurencyjne:

f=(x,n,m=1,i=0,s=x,c=1)=>i<2*n?f(x,n,m*=-x*x/++i/++i,i,s+m*x/++i,c+m):[s,c].map(x=>x.toFixed(8))

Wynik:

f(0.3,1)
["0.29550000", "0.95500000"]

f(0.3,24)
["0.29552021", "0.95533649"]

Nie spełnia to jednak specyfikacji dotyczącej zaokrąglania.
Martin Ender

@ m.buettner naprawiono
MT0

1
Nie spełnia formatu wejściowego i no functionswymagań.
avall

Zaktualizuj swoją odpowiedź. Zobacz szczegóły w pytaniu. Dzięki.
Gaurang Tandon

2

C, 114

Niewystarczająca reputacja do komentowania, ale w odpowiedzi na odpowiedź C Squeamisha Offisrage'a , redukcja 7 bajtów poprzez użycie liczby zmiennoprzecinkowej do podwójnego i usuwania spacji oraz połączenie deklaracji i inicjalizacji „r” daje

float s,c,r=1,x;main(i,n){for(scanf("%f%d",&x,&n);i<n*2;s+=r,r*=-x/i++)c+=r,r*=x/i++;printf("%.8f\n%.8f\n",s,c);}

spróbuj tutaj .


Witamy w programowaniu zagadek i golfa kodowego. Dobra robota, jeśli chodzi o potwierdzenie, że twoja odpowiedź jest niewielkim ulepszeniem @ squeamishossifrage (wciąż udało mi się przeliterować ją źle w mojej edycji). Najlepiej nie odwoływać się do odpowiedzi „powyżej”, ponieważ kolejność zmienia się przy każdej edycji. BTW, zauważyłem inicjalizację rw deklaracji. Nie testowałem, aby sprawdzić, czy floatdaje wymaganą precyzję.
Level River St

@steveverrill Nie sądziłem, floatże dałbym wymaganą precyzję, ale to działa :) Witamy w PPCG, user2702245!
Gaurang Tandon

Czy to tylko ja dostaję złe odpowiedzi ze floatzmiennymi? Za x=5i n=3dostaję sin(x)=10.20833206i cos(x)=14.54166412:-( (Intel Core Duo, na wypadek gdybyś się zastanawiał)
piskliwy ossifrage

Czy chciałbym, żebym przekonwertował to na komentarz do wspomnianej odpowiedzi?
Klamka

@Doorknob May również zostaw to teraz :-)
piskliwy ossifrage

2

GNU bc, sterowany przez bash, 128 bajtów

Zbyt wiele bajtów wydano na ustawienie miejsc po przecinku i na najbliższe zaokrąglenie. No cóż, tutaj jest tak:

bc -l<<<"m=1000000
w=s=$1
c=1
for(p=2;p/2<$2;s+=w){w*=-1*$1/p++
c+=w
w*=$1/p++}
s+=((s>0)-.5)/m
c+=((c>0)-.5)/m
scale=6
s/1
c/1"

Wynik:

$ ./trig.sh 5 3
10,208333
14,541667
$ ./trig.sh 8.555 13
.765431
-6,641092
$ ./trig.sh 9,26 10
-3,154677
-8,404354
$ ./trig.sh 6,54 12
.253986
.967147
$ ./trig.sh 5 1
5,000000
1,000000
$ ./trig.sh 20 20
-5364,411846
-10898,499385
$ 

Narzędzia wiersza polecenia systemu Linux, 97 znaków Unicode

Odpowiedź hacka Unicode usunięta na żądanie OP. Spójrz na historię edycji, jeśli jesteś zainteresowany.


Nie lubię zmieniać reguł po opublikowaniu pytania, ale nie zezwalam na znaki zezwalające na kompresję kodu Unicode, ponieważ nie wiedziałem, że znaki Unicode mogą być używane do kompresji kodu. Teraz można używać tylko znaków ASCII. Edytuj swój post. Przepraszamy za niedogodności
Gaurang Tandon

@GaurangTandon To nie jest tak naprawdę kompresja - wersja unicode faktycznie zajmuje więcej bajtów (ale mniej znaków). Ale zgadzam się z twoim sentymentem - faktycznie wolę punktację niż ściśle przy użyciu liczby bajtów, ale nie mogłem się oprzeć odrobinie chińskich znaków w twoim OP.
Cyfrowa trauma

Używasz nielegalnego operatora wykładniczego
avall

@avall Oops. Kosztowało mnie to 4 bajty.
Cyfrowa trauma

1

Ruby, 336

Prawdopodobnie najdłuższy tutaj, ale jestem pewien, że można go skrócić :(

def f(n)
n==0 ? 1: 1.upto(n).inject(:*)
end
def p(x,y)
i=1
return 1 if y==0 
y.times {i *= x}
i
end
def s(x,n)
a = 0.0
for k in 0...n
a += p(-1,k) * p(x.to_f, 1+2*k)/f(1+2*k)
end
a.round(8)
end
def c(x,n)
a= 0.0
for k in 0...n
a +=p(-1,k) * p(x.to_f, 2*k)/f(2*k)
end
a.round(8)
end
x = gets.chomp
n = gets.chomp.to_i
puts s(x,n), c(x,n)

1

JavaScript (ES6) - 185 znaków

i=(h,n)=>n?h*i(h,n-1):1;q=x=>x?x*q(x-1):1;p=(a,j,n)=>{for(c=b=0,e=1;c++<n;j+=2,e=-e)b+=e*i(a,j)/q(j);return b.toFixed(6)}
_=(y=prompt)().split(" ");y(p(_[0],1,_[1])+"\n"+p(_[0],0,_[1]))

Korzysta z funkcji qsilnia, ipotęgowania i pwykonywania zarówno, jak sini cos. Uruchom na jsbin.com. Używa dokładnie formuły bez żadnych modyfikacji.

EDYCJA : Zmieniono 8miejsca 6dziesiętne na miejsca dziesiętne. 15 / maja / 14

Nieskluczony kod :

/*Note that `name=args=>function_body` is the same as `function name(args){function_body} */

// factorial
function fact(x) {
    return x > 1 ? x * fact(x - 1) : 1
}

// Exponentiation
function expo(number, power){
    return power > 0 ? number * expo(number, power - 1) : 1;
}

function sin_and_cos(number, starter, terms) {
    for (count = sum = 0, negater = 1;
            count++ < terms;
            starter += 2, negater = -negater) 

        sum += (negater * expo(number, starter)) / fact(starter);

    // to 6-decimal places
    return sum.toFixed(6);
}

input = (out = prompt)().split(" ");

out(sin_and_cos(input[0], 1,input[1]) 
        + "\n" +                
        sin_and_cos(input[0], 0, input[1]));

1

JavaScript - 133 znaki

y=(z=prompt)().split(" "),s=[0,0],l=1;for(i=0;i<y[1]*2;i++){s[i%2]+=i%4>1?-1*l:l;l*=y[0]/(i+1)}z(s[1].toFixed(6));z(s[0].toFixed(6));

Nie golfił

var y = prompt().split(" ");

var out = [0,0]; // out[1] is sin(x), out[0] is cos(x)
var l = 1; // keep track of last term in series
for (var i=0; i < y[1] * 2; i++) {
    out[i % 2] += (i % 4 > 1) ? -1 * l : l;
    l *= y[0] / (i + 1);
}

prompt(out[1].toFixed(6));
prompt(out[0].toFixed(6));

Dane wejściowe muszą być dwiema liczbami całkowitymi oddzielonymi spacjami, a nie dwoma różnymi oknami dialogowymi. Proszę to naprawić.
Gaurang Tandon

@GaurangTandon naprawiono - dzięki za wskazanie
James


1

Ruby - 160 152 140 znaków

Wykorzystując rekurencję i fakt, że dla tej rekurencyjnej implementacji sin (x, 2n + 1) = 1 + cos (x, 2n - 1), będąc sin (x, n) i cos (x, n), szereg zdefiniowany powyżej dla cos x i sin x.

p=->x,n{n<1?1:x*p[x,n-1]}
f=->n{n<2?1:n*f[n-1]}
c=->x,n{n<1?1:p[x,n]/f[n]-c[x,n-2]}
x,n=gets.split.map &:to_f
n*=2
puts c[x,n-1]+1,c[x,n-2]

Edycja: przesłane przez komentujących (czytaj poniżej).


1
Można zaoszczędzić dużo znaków za pomocą lambdy: p=->x,n{...}, f=->n{...}i tak dalej, a następnie za pomocą nawiasów kwadratowych nawiasach zamiast do nich zadzwonić, jak p[x,n-1]. Myślę też, że collectjest to po prostu alias map, który jest znacznie krótszy, a ponieważ mapujesz tylko połączenie członka, możesz go skrócić gets.split.map &:to_f.
Martin Ender

@ MartinBüttner Dzięki! Dodam to! (mam nadzieję, że Twój komentarz tutaj stwierdził, że to rozwiązanie jest nie tylko moje, ale współpracuje) Szczerze mówiąc: jestem również nowy w Ruby (tylko 2 miesiące) :)))
Boriel
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.