Пусть тригонометрия начинается!


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. Ввод должен быть через стандартный ввод или диалоговое окно (если ваш язык не поддерживает стандартный ввод)

Выход:

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

Значение обоих sin(x)и cos(x)должно быть округлено до 6 знаков после запятой. Если sin(x)есть 0.5588558855(10 десятичных цифр), его следует округлить до 0.558856(6 десятичных цифр). Округление должно происходить до ближайшего, как описано в пятом столбце «Округление до ближайшего» таблицы в этой статье вики .

Ограничения:

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, а не китайские символы Юникода, которые допускают сжатие кода.
  5. Ваша программа должна завершиться и отобразить вывод в течение 3 секунд после ввода.
  6. Ваш ответ должен сопровождать незакрашенный код вместе с объяснением кода (обязательно, если код не сразу очевиден для программистов, незнакомых с вашим языком, особенно GolfScript, J и т. Д.).
  7. Пожалуйста, включите ссылку на онлайн-компилятор, где ваша программа может быть протестирована.

Подсчет очков:

Ответ с наименьшей длиной кода в символах, включая пробелы, символы табуляции и т. Д., Выигрывает! Победитель будет объявлен 21 мая 2014 года.

РЕДАКТИРОВАТЬ : 21/05/14 Победитель Aditsu с использованием языка CJam . Занявший второе место следует за jpjacobs с языком J , а второй занял первое место с языком Perl . Поздравляю всех!


(Примечание к моду: комментарии обнажены. Пожалуйста, пропишите мне любую потерянную информацию, которая может вам понадобиться; похоже, после моего предупреждения все
встало

В первом абзаце должно быть «синус», а не «грех»
не то, чтобы Чарльз

Требуется ли « округление до ближайшего» или мы можем использовать какие-либо встроенные средства округления? например, к нулю?
Цифровая травма

Требование эквивалента mod 2piоперации для ускорения сходимости входных данных было бы весьма полезно - это одно из многих улучшений, которые реальный мир использует при работе с этими функциями. (на самом деле мод пи и знак осведомленности).
Флорис,

1
@ Флорис, я никогда этого не знал. Что ж, сейчас мы ничего не можем сделать, правила уже сильно изменились, и я не хочу их менять, чтобы еще больше раздражать ответчиков. Спасибо за предложение, хотя!
Гауранг Тандон

Ответы:


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; это "/ к!" часть расчета вместе с изменением знака
X*умножается на X; это «X ^ k» часть расчета; мы получили следующее слагаемое в серии,
_дублирующее слагаемое, которое будет использоваться для вычисления следующего слагаемого в следующей итерации
;(после цикла). выскакивает последний дублируемый слагаемый,
]собирающий слагаемые в стеке в массив.
В этот момент у нас есть массив [ 1 Х-Х ^ 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 мест по умолчанию, как удобно!


Алгоритм

Изучение ряда Тейлора для греха (х) :

можно видеть, что каждый член равномерно делит каждый последующий член. Из-за этого его можно довольно легко преобразовать во вложенное выражение:

cos (x) преобразуется аналогично, без начального x , а знаменатель слагаемых на единицу меньше.

Кроме того, это вложенное выражение может быть переформулировано как обратное рекурсивное выражение:

с s = 0 и sin (x) = x · s 1 , что в конечном итоге и используется.


Ungolfed

<> =~ 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
Какой хитрый способ разобрать входные данные ... могу ли я использовать это в своем решении? :)
Тал

@ Тал Не стесняйтесь.
Примо

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

Ungolfed:

<> =~ / /;
$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.
Гауранг Тандон

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

Я злоупотребляю неявной типизацией, но, к сожалению, такого неявного сложного типа не существует, поэтому мне пришлось указать это и комплекс i. Gfortran естественным образом сокращает вывод на 8 знаков после запятой, поэтому мы хорошо справляемся с этой задачей. К сожалению, мой оригинальный метод вывода print*,tне соответствовал спецификациям, поэтому мне пришлось добавить 16 символов для вывода мнимых и реальных компонентов и указать требуемые 8 десятичных знаков.

Благодаря Ventero мне удалось сохранить 23 байта между выводом и циклом. И еще один персонаж для получения правильных ответов и форматированного вывода. И еще 3 на readзаявлении.

Ungolfed,

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

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

Чтобы сохранить байт, операторы, которые обновляют значение синуса, помещаются внутри for()оператора, но фактически выполняются после операторов после закрывающей скобки, которые обновляют значение косинуса. (Думаю, я мог бы также сохранить еще пару байтов, удалив последний символ новой строки в выходных данных программы.)

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

Ungolfed:

Вот код с небольшой перестановкой, чтобы сделать порядок, в котором все делается немного яснее:

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циклом


Здравствуйте, я недавно отредактировал правила, которые теперь не позволяют встроенным операторам возвести в степень (это то, **что я делаю, я полагаю). Итак, я думаю, вам придется редактировать свой ответ. Приносим извинения за неудобства. Пожалуйста, поправьте меня, если я ошибаюсь.
Гауранг Тандон

1
Я думаю, что дальнейшие модификации бесполезны с ответом xnor :)
апреля

@avail On 20 20, я получаю вывод -5364.4118142500001. Могу хотеть исправить это до 8 десятичных знаков.
Гауранг Тандон

Это из-за repl.it Python версии 2.7.1. Если вы запустите его на ideone.com (Python 2.7.3), он будет работать правильно. ideone.com/JsYNNK
августа

Теперь это работает хорошо! +1
Гауранг Тандон

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 переменных вместо массива для вывода упрощает цикл.

Ungolfed

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)в некоголенном коде.
Гауранг Тандон

1
@GaurangTandon исправлено
edc65

2

JavaScript (ECMAScript 6 Draft) - 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требованиям.
до

Пожалуйста, обновите свой ответ. Смотрите детали в вопросе. Благодарю.
Гауранг Тандон

2

С, 114

Недостаточная репутация для комментариев, но в дальнейшем C брезгует Offisrage в ответ , 7 сокращение байт с помощью поплавка для двойных и удаления пробелов и объединения декларации и инициализацией из «г» дает

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дает необходимую точность.
Уровень Река St

@steveverrill Я тоже не думаю, floatчто даст необходимую точность, но это работает :) И добро пожаловать в PPCG, user2702245!
Гауранг Тандон

Это только я получаю неправильные ответы с floatпеременными тогда? За x=5и n=3получаю sin(x)=10.20833206и cos(x)=14.54166412:-( (Intel Core Duo, если вам интересно)
брезгливый оссифраж

Вы хотите, чтобы я преобразовал это в комментарий к указанному ответу?
Дверная ручка

@ 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
0,765431
-.641092
$ ./trig.sh 9,26 10
-3,154677
-8,404354
$ ./trig.sh 6,54 12
0,253986
0,967147
$ ./trig.sh 5 1
5.000000
1.000000
$ ./trig.sh 20 20
-5364,411846
-10898,499385
$ 

Инструменты командной строки Linux, 97 символов Юникода

Unicode взломанный ответ удален по запросу OP. Посмотрите историю изменений, если вам интересно.


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

@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. Использует именно формулу без каких-либо изменений.

РЕДАКТИРОВАТЬ : Изменено8 десятичные разряды на 6десятичные разряды. 15 / Май / 14

Код Ungolfed :

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

Ungolfed

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

Ввод должен быть двумя целыми числами, разделенными пробелами, а не в двух разных диалоговых окнах. Пожалуйста, исправьте это.
Гауранг Тандон

@ GaurangTandon исправлено - спасибо за указание на это
Джеймс


1

Рубин - 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 Спасибо! Добавлю это! (надеюсь, что ваш комментарий здесь заявил, что это решение не только мое, но и коллаборация) Если честно: я также новичок в ruby ​​(только 2 месяца) :)))
Boriel
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.