Нехай починається тригонометрія!


20

Вступ:

Синусоїдальної з xдається формулою:

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

Косинусного з xдається формулою:

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

Завдання:

Враховуючи значення xі n, напишіть програму (без функцій тощо), щоб вивести значення sin(x)та cos(x)виправити до nвищезазначених формул. Припустимо, що xв радіанах.

Вхід:

x n

Десяткове число x(з до 3 знаків після коми) і цілим числом n. Введення має бути в stdin або діалоговому вікні підказки (якщо ваша мова не підтримує stdin)

Вихід:

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

Значення обох sin(x)і cos(x)має бути округлене до 6 знаків після коми. Якщо sin(x)є 0.5588558855(10 десяткових цифр), його слід округлити до 0.558856(6 десяткових цифр). Округлення повинно відбуватися до найближчої, як описано у п’ятому стовпці "Раунд до найближчого" таблиці в цій статті Wiki .

Обмеження:

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

Зразки:

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

Примітки:

  1. Стандартні лазівки заборонені.
  2. Вбудовані математичні функції та оператори тригонометрії (sin, cos, tan тощо), факториальні та експоненціації не можуть бути використані. Ви можете використовувати вбудовану функцію округлення для оцінки результатів обчислень sin(x)та cos(x)до 6-ої десяткової цифри.
  3. Не потрібно обробляти неправильні введення.
  4. У програмі можуть використовуватися лише символи ASCII, а не китайські Unicode, які дозволяють стиснути код.
  5. Ваша програма повинна припинити та відобразити результат протягом 3 секунд після введення.
  6. Ваша відповідь повинна супроводжувати код, який не використовується для нього, разом із поясненням коду (обов'язковий, якщо код не очевидний для програмістів, які не знайомі з вашою мовою, особливо GolfScript, J тощо).
  7. Додайте посилання на онлайн-компілятор, де можна перевірити вашу програму.

Оцінка:

Відповідь з найменшою довжиною коду в символах, включаючи пробіли, вкладки тощо, виграє! Переможець буде оголошений 21 травня 2014 року.

EDIT : 21/05/14 Winner - це aditsu, використовуючи мову CJam . Забігаючий слід за jpjacobs з мовою J , а другий підбіг - це прим з мовою Perl . Вітаю всіх!


(Зауваження мода: коментарі нульові. Будь ласка, поштовхуйте мене за будь-якою втраченою інформацією, яка, можливо, захочете; схоже, після мого попередження заздалегідь, все все стало своїм питанням.)
Doorknob

У першому абзаці має бути "синус", а не "гріх"
Не те, щоб Чарльз

Чи залишається вимогою "Круглий до найближчого" чи ми можемо використовувати будь-які вбудовані засоби округлення? наприклад, кругла до нуля?
Цифрова травма

Вимагати еквівалента mod 2piоперації з метою швидшого зближення входів було б досить корисно - це одне з багатьох удосконалень, які використовує реальний світ при роботі з цими функціями. (власне мод пі та підписує обізнаність).
Флоріс

1
@Floris Я цього ніколи не знав. Ну, ми нічого не можемо зробити зараз, правила вже сильно змінилися, і я не хочу продовжувати їх змінювати, щоб ще більше дратувати відповідачів. Дякую за пропозицію, хоча!
Гауранг Тадон

Відповіді:


6

CJam - 42

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

Спробуйте в Інтернеті за адресою http://cjam.aditsu.net

Пояснення:

rчитає маркер з вхідного
dперетворення на подвійне,
:Xприсвоює змінній X
;спливаюче значення зі стека
1ставить 1 на стек (перший доданок)
_дублює 1
rзчитує наступний жетон (n)
iперетворюється на ціле число
2*,1>{...}/- це певний цикл з 1 до 2 * n - 1:
- 2*множиться на 2
- ,робить масив від 0 до (останнє значення) -1
- 1>видаляє перший елемент масиву (0)
- {...}/виконує блок для кожного елемента в масиві
_дублює цикл " змінна "(назвемо це k)
2%2*(перетворює з парного / непарного в -1/1:
- 2%є модуль 2 (-> 0/1)
- 2*помножується на 2 (-> 0/2)
-(декременти (-> -1/1)
*помножуються, змінюючи таким чином знак кожен раз,
/ділить додаток на стеку на k або -k; це "/ k!" частина обчислення разом зі знаком зміни
X*множиться на X; це "X ^ k" частина обчислення; ми отримали наступний термін у серії
_дублює термін, який буде використаний для обчислення наступного терміна в наступній ітерації
;(після циклу), спливає останній дублюваний термін,
]збирає умови в стеку в масив.
На даний момент у нас є масив [ 1 X -X ^ 2/2! -X ^ 3/3! X ^ 4/4! X ^ 5/5! ...], що містить точно всі умови, які нам потрібні для cos (x) та sin (x), перемежоване
2/розбиває цей масив на пари
zтранспортує матрицю, в результаті чого масив із умовами cos (x) та масив із умовами sin (x), оскільки "рядки матриці"
{...}/знову виконують блок для кожного елемента масиву (рядок матриці):
- :+додає елементи рядка матриці разом
- 6mOокругляє до 6 десяткових знаків
У цей момент у нас є бажаний cos (x), а sin (x) на стеку
pдрукує подання останнього елемента на стеку (sin (x)), а потім новий рядок
At в кінці програми, решта вмісту стеку (cos (x)) надрукується автоматично.


1
+1 за ознайомлення з мовою, про яку я ніколи не чув і, мабуть, ніколи не буду користуватися.
Олексій А.

@ Алекс дякую, CJam дещо схожий на GolfScript на стероїди
aditsu

Мені не подобається змінювати правила після публікації запитання, але я заборонив символи Unicode, що дозволяють стиснення коду, оскільки я не знав, що символи Unicode можуть використовуватися для стиснення коду. Зараз можна використовувати лише символи ASCII. Відредагуйте свою публікацію. Вибачте за незручності.
Гауранг Тадон

@GaurangTandon мені це теж не подобається. Що ще, на вашу думку, китайські символи могли використати у цій проблемі? У всякому разі, відредаговано.
aditsu

18

Perl - 72 байти

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

Або, рахуючи параметри командного рядка як 1 байт кожен, у 70 байтах :

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

Або, якщо ви дозволите мені Perl 5.8, в 63 байти :

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

але чому б ти.

Редагувати : Дотримання нових правил. %fтури до 6 місць за замовчуванням, як зручно!


Алгоритм

Вивчаючи ряд Тейлора на гріх (x) :

видно, що кожен термін рівномірно ділить кожен наступний член. Через це він може бути перетворений досить легко у вкладений вираз:

cos (x) перетворюється аналогічно, без провідних х , а знаменник доданків один менший.

Крім того, цей вкладений вираз можна переформулювати як зворотний рекурсивний вираз:

при s = 0 і sin (x) = x · s 1 , що в кінцевому підсумку і використовується.


Безумовно

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

Використання зразка

$ 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

Якщо ви хочете протестувати це в Інтернеті, рекомендую скористатися compileonline.com . Скопіюйте-Вставте код у main.pl, а потім введіть у STDINполе Execute Script.


2
Який хибний спосіб проаналізувати дані ... чи можу я використовувати це у своєму рішенні? :)
Тал

@Tal Відчувайте себе безкоштовно.
примо

2
Я думаю, що perl (і особливо ваш код) вважається "не відразу очевидним для програмістів, які не знайомі з вашою мовою"
aditsu

1
@aditsu Погодився. Додаю чистіший код та пояснення алгоритму.
примо

2
Ця відповідь справді була надзвичайно навчальною!
Тал

10

Пітон 3 (102) / Пітон 2 (104)

Пітон 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)

В основному той самий код. Ми врятуємо два символи, не вимагаючи паронів, printале чотири втрачаємо від необхідності raw_input.

Вибірка зразка

Ви можете запустити їх тут .

>>>
20 20
-5364.411846
-10898.499385

Пояснення коду

Основна ідея - обчислити 2*nтерміни e^(ix), а потім взяти уявну та реальну частину, щоб отримати значення sinта cosзначення, наближені до nтермінів. Ми використовуємо усічення серії Тейлора:

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

Це многочлен у i * x, але замість того, щоб обчислити його значення шляхом підсумовування кожного члена, ми використовуємо модифікований метод Горнера для обчислення послідовності (визначеної рекурсивно в зворотному порядку)

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

що дає t_1рівне бажане значення.

Операції форматування рядків Python використовуються для отримання значень для відображення округлими до 6 знаків після коми.

Редагувати: Змінено на круглий на 6 цифр відповідно до нових правил. Інші зміни не потребували.


Спробуйте ideone для онлайн-перекладача py3 :)
Гаррі Бідл

@BritishColour Дякую! Я додав це до публікації.
xnor

Будь ласка, оновіть свою відповідь. Дивіться детальну інформацію. Спасибі.
Гауранг Тадон

8

J 98 70 69 58

Хоча це, ймовірно, може бути скорочене трохи, використовуючи більш фантазійні функції ... коментарі вітаються:

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

Примітка 2: вхід закінчується при отриманні EOF (ctrl-D в Linux). Edit: приєднатися і зведення в ступінь факторіала в краще, більш J-Робочі цілому: ($ %&(*/) >:@i.@[ ). Це зводиться, щоб взяти масив x реплікацій y та масив чисел від 1 до y. Помножте кожен і поділіть результат. Це позбавляється від дубліката */.

Завдяки algortihmshark вимкнено ще 7 символів.

Усунутий зріз для позбавлення від нижньої лінії.

Більш довга версія, для якої знання про виделки є обов'язковим.

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''

Немає онлайн-перекладача J, але він є відкритим кодом з кількох років; встановлення легко за допомогою цих інструкцій:

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

На #jsoftware на irc.freenode.org також є бот J.

stdin працює лише тоді, коли працює з файлу, з командного рядка, інакше заміняється stdin ''тим, 'a b;'де a і b - числа, які були б передані в командному рядку.


5
Мені подобається, що це починається зexit
Digital Trauma

Будь ласка, оновіть свою відповідь. Дивіться детальну інформацію. Спасибі.
Гауранг Тадон

Оновлено для 6 знаків після коми. Якщо є щось інше, будь ласка, вкажіть. Дякую
jpjacobs

Ви можете видалити &з, 0j6&":щоб зберегти картку. Також, (i.@(,&_2)@{:($%&(*/)>:@i.@[)"0{.)можна переписати (($%&(*/)1+i.@[)"0~i.@,&_2)/ще на 6.
Алгоритми

Це завдання кричить T.(приблизна функція n-термінового ряду Тейлора), але я думаю, що це багатослівний як стандартна лазівка.
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

Безголівки:

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

Перший рядок зчитує вхід і використовує регулярний вираз, щоб знайти пробіл; це автоматично ставить значення перед пробілом у $ `і значення після нього в $ '.

Тепер петлю від 1 до 2*n-1. $t- наш термін, який цикл неодноразово множується на xта ділиться на індекс циклу ( $_). Цикл починається з 1, а не з 0, оскільки косинус ініціалізований на 1, що врятувало мене з ділом на нуль.

Після оновлення $tтринаціональний оператор повертає або, $sineабо $cosineзалежно від того, чи є непарний або парний індекс, і додає йому $tзначення. Магічна формула $_&2?-$t:$tвизначає, чи потрібно додавати чи віднімати це значення (в основному, використовуючи побітові позначки та за індексом та 2 для створення повторюваної послідовності "додавання, додавання, віднімання, віднімання").

Ви можете перевірити запуск цього коду на compileonline.com .


Виправте результат для 20 20.
Gaurang Tandon

1
Я думаю 1..$n*2-1, що замість цього може знадобитися перехід до вашого циклу 1..$n. Поки я тут ... $sпрекрасно залишається неініціалізованим, як undefоцінюється 0в числовому контексті. Троичное призначення не потребує в дужках: $_&1?$s:$c+=$t. "%.8f\n%.8f"може бути скорочено до "%.8f\n"x2, як наслідок, додавання нового рядка.
примо

@Primo Спасибі, я не знав про деякі з них. І тепер це навіть дає правильний результат.
Тал

@Tal Моє задоволення. Також трохи краща магія: $t*(1-($_&2))=> $_&2?-$t:$t.
примо

Будь ласка, оновіть свою відповідь. Дивіться детальну інформацію. Спасибі.
Гауранг Тадон

5

Фортран: 89 109 125 102 101 98 байт

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

Я зловживаю неявним введенням тексту, але, на жаль, такого неявного складного типу не існує, тому мені довелося вказати це & the kompleks i. Gfortran природним чином скорочує вихід на 8 знаків після коми, тому ми добре в цій специфікації. На жаль, мій оригінальний метод виведення, print*,tне відповідав специфікаціям, мені довелося додати 16 символів для виведення уявних та реальних компонентів і потрапити на необхідні 8 десяткових знаків.

Завдяки Ventero мені вдалося зберегти 23 байти між виходом і циклом. І ще один символ, щоб отримати правильні відповіді та відформатований вихід. І ще 3 на readзаяву.

Безумовно,

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

Будь ласка, оновіть свою відповідь. Дивіться детальну інформацію. Спасибі!
Гауранг Тадон

1
@GaurangTandon: Напевно, слід припинити змінювати деталі проблеми.
Кайл Канос

Я знаю, і цього не хочу, але не можу в цьому допомогти. Власне, перевіривши 5 відповідей, виявилося, що майже всі вони давали різні результати (це було справді зовсім не підозрювано). Я міг би дотримуватися іншого підходу, але це вимагало б повної зміни алгоритмів поточних відповідей. Це найкраще, що я міг зрозуміти.
Гауранг Тадон

2
Ну я знаю, що моя добре працює, тому я повинен повністю отримати чек: D;)
Кайл Канос

4

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

Щоб зберегти байт, оператори, що оновлюють значення sine, розміщуються всередині for()оператора, але насправді виконуються після операторів після закритих дужок, які оновлюють значення косинуса. (Напевно, я також міг би зберегти ще пару байтів, видаливши остаточний символ нового рядка у виході програми.)

Глобальні змінні s, c, rі xнеявно инициализируется нуль, і iбуде мати значення 1 до тих пір, поки немає аргументів , передбачених в командному рядку. На жаль, printf()за замовчуванням розміщено 6 місць десяткових знаків, тому формат виводу є трохи багатослівним.

Безголівки:

Ось код із трохи перестановкою, щоб зробити порядок, у якому все робиться трохи чіткіше:

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

Вибірка зразка:

$ echo 1.23 4 | ./sincos
0.94247129
0.33410995

Спробуйте в Інтернеті:

http://ideone.com/URZWwo


3

Python> = 2.7.3, 186 184 211 200 182 170 символів

Ніби простий, як пекло. Використовує формулу з питання, параметризованого для синуса і косинуса.

Інтернет-перекладача можна знайти тут тут

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

Редагувати: Дійсна версія з усіма обмеженнями

Edit2: Змінено онлайн-інтерпретатора на ideone.com через недійсну roundфункцію в Python 2.7.1

Edit3: Виявилося, що я використовував непотрібну лямбда-вбудований + змінив округлення до строкового формату (викрадено з xnor :))

Edit4: замінено joinнефункціональним основним forциклом


Здравствуйте, я нещодавно відредагував правила, які зараз не дозволяють вбудованим операторам експоненціювати ( **я вважаю, що це робиться). Отже, я думаю, вам доведеться відредагувати свою відповідь. Вибачте за незручності. Будь ласка, виправте мене, якщо я помиляюся.
Gaurang Tandon,

1
Я думаю, що подальші модифікації будуть марними з відповіддю xnor :)
avall

@avail Увімкнено 20 20, я отримую вихід -5364.4118142500001. Ви можете зафіксувати це до 8 десяткових знаків.
Гауранг Тадон

Це через версію repl.it Python 2.7.1. Якщо ви запускаєте його на ideone.com (Python 2.7.3), він працює належним чином. ideone.com/JsYNNK
avall

Це добре працює зараз! +1
Gaurang Tandon

3

JavaScript - 114 символів

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

На основі чудової відповіді Джеймса. Той же алгоритм, перший крок уникнути з ініціалізацією c = 1 і s = x. Використання 2 vars замість масиву для виведення спрощує цикл.

Безумовно

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

Невелика друкарська помилка: Це було б, s += (l *= x / ++d)а не s += (l* = x / ++d)в коді, який не має сили.
Gaurang Tandon

1
@GaurangTandon fix
edc65

2

JavaScript (проект ECMAScript 6) - 97 96 символів

Рекурсивне рішення:

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

Вихід:

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

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

Це не відповідає специфікації щодо округлення.
Мартін Ендер

@ m.buettner виправлено
MT0

1
Він не відповідає формату введення та no functionsвимогам.
avall

Будь ласка, оновіть свою відповідь. Дивіться детальну інформацію. Спасибі.
Гауранг Тадон

2

С, 114

Недостатня репутація для коментування, але, крім відповіді С на Squeamish Offisrage , зменшення на 7 байтів за допомогою використання float для подвійного та вилучення пробілів, а також поєднання оголошення та init з 'r' дає

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

спробуйте тут .


Ласкаво просимо до програмування головоломок та коду для гольфу. Молодці, щоб визнати, що ваша відповідь є незначним покращенням на @ squeamishossifrage's (я все-таки встиг записати це неправильно у своїй редакції.) Найкраще не посилатися на відповідь "вище", тому що порядок змінюється щоразу, коли відбувається редагування. До речі, я помітив ініціалізацію rв декларації. Я не перевіряв, чи floatдає потрібна точність.
Річка Рівня Св

@steveverrill Ні я не думав, floatщо дасть необхідну точність, але це працює :) І ласкаво просимо до PPCG, user2702245!
Gaurang Tandon

floatТоді я просто отримую неправильні відповіді зі змінними? Для x=5і n=3, я отримую sin(x)=10.20833206і cos(x)=14.54166412:-( (Intel Core Duo, на випадок, коли вам було цікаво)
писклявий ossifrage

Чи хотіли б я перетворити це на коментар до сказаної відповіді?
Дверна ручка

@Doorknob травня , а також залишити його зараз :-)
гидливо грифа

2

GNU bc, керований bash, 128 байт

Занадто багато байтів витратили на встановлення десяткових знаків та найближче округлення. Ну добре, ось це все одно:

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"

Вихід:

$ ./trig.sh 5 3
10.208333
14.541667
$ ./trig.sh 8,555 13
.765431
-.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
$ 

Інструменти командного рядка Linux, 97 символів unicode

Відповідь на злом Unicode видалено на вимогу ОП. Подивіться історію редагування, якщо вам це цікаво.


Мені не подобається змінювати правила після публікації запитання, але я заборонив символи Unicode, що дозволяють стиснення коду, оскільки я не знав, що символи Unicode можуть використовуватися для стиснення коду. Зараз можна використовувати лише символи ASCII. Відредагуйте свою публікацію. Вибачте за незручності
Gaurang Tandon

@GaurangTandon Його насправді не стиснення - версія unicode насправді займає більше байтів (але менше символів). Але я погоджуюсь з вашими настроями - я фактично вважаю за краще забивати скоринг, використовуючи кількість байтів, але не зміг протистояти трохи китайським символам у вашій ОП.
Цифрова травма

Ви використовуєте нелегальний експонентний оператор
Avall

@avall На жаль Це коштувало мені 4 байти.
Цифрова травма

1

Рубі, 336

Напевно, найдовший тут, але я впевнений, що його можна було скоротити :(

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 символів

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

Використовує функцію qдля факторіалу, iдля експоненції та pдля виконання і sinта, і cos. Запуск на jsbin.com. Використовує саме формулу без будь-яких змін.

EDIT : Змінено 8десяткові знаки на 6десяткові. 15 / травень / 14

Код без вогню :

/*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 символів

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

Безумовно

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

Вхід повинен бути двома цілими числами, розділеними пробілом, а не в двох різних діалогових вікнах. Виправте це.
Gaurang Tandon

@GaurangTandon виправлено - дякую, що вказав на це
Джеймс


1

Ruby - 160 152 140 символів

Використовуючи рекурсію і той факт, що для цієї рекурсивної реалізації sin (x, 2n + 1) = 1 + cos (x, 2n - 1), будучи sin (x, n) і cos (x, n) рядами, визначеними вище для cos х і гріх х.

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]

Редагувати: Опубліковано коментаторами (читайте нижче).


1
Ви можете заощадити багато символів за допомогою лямбда: p=->x,n{...}, f=->n{...}і так далі, а потім використовувати квадратні дужки замість круглих дужок називати їх, як p[x,n-1]. Також, я думаюcollect це лише псевдонім для map, який набагато коротший, і оскільки ви лише відображаєте виклик учасника, ви можете скоротити його до gets.split.map &:to_f.
Мартін Ендер

@ MartinBüttner Дякую! Додамо це! (сподіваюсь, ваш коментар тут зазначав, що це рішення не тільки моє, але й колабс) Чесно кажучи: я теж новачок у рубіні (лише 2 місяці) :)))
Boriel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.