Быстрые тригонометрические расчеты
Ваша задача - создать программу, которая может вычислять синус, косинус и тангенс угла в градусах.
правила
- Нет встроенных тригонометрических функций (даже секущих, косекансных и котангенсных, если они есть в вашем языке).
- Вы можете использовать справочные таблицы, но их общий размер не должен превышать 3000 элементов (для всех трех операций вместе взятых). Пожалуйста, сделайте так, чтобы он читал таблицы из файла (например
trig.lookup
), чтобы они не перепутали код. - Нет доступа к сети.
- Вы должны правильно округлить вывод, как описано ниже. Не используйте пол или потолок.
- Вы можете использовать любой метод для вычисления значений, например, непрерывные дроби , если это правильно до 7 значащих цифр.
- Ваш код должен уметь рассчитывать время. Исключите из своего времени операции файлового ввода-вывода, поэтому просто рассчитайте время для функций, которые выполняют триггер и любое округление.
- Я должен быть в состоянии запустить ваш код. Пожалуйста, опубликуйте ссылку на свободно доступный компилятор / интерпретатор и дайте инструкции, необходимые для компиляции / запуска кода (например, какие параметры передать в GCC).
- Применяются стандартные лазейки .
Формат ввода
- Читайте из файла, который называется,
trig.in
если только ваш язык не поддерживает файловый ввод / вывод. - Углы между 0 и 360 включительно.
- Ввод будет состоять из углов до десяти значащих цифр в десятичных разрядах, разделенных новыми строками. Например:
90,00000000
74,54390000
175,5000000
Выходной формат
- Для каждого предоставленного угла вы должны вывести его синус, косинус и касательную к 7 значащим цифрам, разделенным пробелами, в одной строке. Используйте «научное обозначение», например,
1.745329E-5
дляtan 0.001
или1.000000E+0
дляsin 90
. - Обозначим бесконечность или NaN
n
, например, вывод для90.00000000
должен быть1.000000 0.000000 n
. - Если входной сигнал состоит из трех углов, разделенных символами новой строки, выходные данные должны состоять из трех строк, каждая из которых содержит синус, косинус и тангенс.
- Вы не можете выводить что-либо еще.
- Вывод в файл называется,
trig.out
если ваш язык не поддерживает файловый ввод / вывод.
счет
- быстрый код . Задача состоит в том, чтобы написать программу, которая вычисляет эти три значения как можно быстрее. Самое быстрое время побеждает.
- Каждый получит один и тот же тестовый ввод из разных углов.
- Время будет записано на моей машине.
- Ваша оценка - это среднее значение трех прогонов на одном входе (очевидно, что вы ничего не можете сохранить между прогонами).
- Время компиляции не включено. Эта проблема больше касается используемого метода, чем языка. (Если бы кто-то мог указать мне, как я исключил бы время компиляции для таких языков, как Java, я был бы очень признателен)
- Моя машина установлена на Ubuntu 14.04. Статистика процессора указана на Pastebin (получена при запуске
cat /proc/cpuinfo
). - Я отредактирую ваше время в вашем ответе, когда я проверю его.
math
fastest-code
trigonometry
Geobits
источник
источник
sin
,cos
иtan
на новой линии. Нужно ли менять его, чтобы выводить ответы в одну строку?Ответы:
Фортран 90
Я использую метод CORDIC с предварительно табулированным массивом из 60 значений arctan (подробности о том, почему это необходимо, см. В вики-статье).
Для этого кода требуется файл
trig.in
со всеми значениями в новых строках, которые должны храниться в той же папке, что и исполняемый файл Fortran. Компилируя это,где
file
имя файла, которое вы ему даете (вероятноSinCosTan.f90
, будет самым простым, хотя не обязательно совпадать с именем программы и именем файла). Если у вас есть компилятор Intel, я бы порекомендовал использоватьпоскольку
-xHost
(который не существует для gfortran) обеспечивает более высокий уровень оптимизации, доступный для вашего процессора.Мои тестовые прогоны давали мне около 10 микросекунд на расчет при тестировании 1000 случайных углов с использованием gfortran 4.4 (4.7 или 4.8 доступно в репозиториях Ubuntu) и около 9.5 микросекунд с использованием ifort 12.1. Тестирование только 10 случайных углов приведет к неопределенному времени с использованием подпрограмм Фортрана, поскольку подпрограмма синхронизации с точностью до миллисекунды, а простая математика говорит, что для выполнения всех 10 чисел требуется 0,100 миллисекунды.
РЕДАКТИРОВАТЬ Я, видимо, рассчитывал IO, который (а) сделал время больше, чем необходимо, и (б) противоречит пункту № 6. Я обновил код, чтобы отразить это. Я также обнаружил, что использование целого
kind=8
числа с внутренней подпрограммойsystem_clock
дает микросекундную точность.С помощью этого обновленного кода я теперь вычисляю каждый набор значений тригонометрических функций примерно за 0,3 микросекунды (значащие цифры в конце меняются от начала к этапу, но он постоянно колеблется около 0,31 мкс), что является значительным сокращением по сравнению с предыдущим Итерация, которая приурочена к IO.
источник
Python 2.7.x или Java (выбирайте сами)
Бесплатный переводчик Python можно скачать здесь .
Бесплатный переводчик Java можно скачать здесь .
Программа может принимать входные данные как из файла с именем
trig.in
расположенного в том же каталоге, что и файл программы. Ввод разделен переводом строки.Первоначально я делал это в Python, потому что - ну, я люблю Python. Но, поскольку я тоже хочу попытаться выиграть, я переписал его в Java позже ...
Версия Python: я получил около 21 мкс за прогон на моем компьютере. Я получил около 32 мкс при запуске его на IDEone .
Версия Java: я получаю около 0,4 мкс за цикл на моем компьютере и 1,8 мкс в IDEone .
Спецификации компьютера:
Тестовое задание:
sin
,cos
иtan
все углы ввода.Тестовый вход, используемый для обоих, выглядит следующим образом:
О Кодексе
. Исходным условием для этой программы была оценка
sin
иcos
использование их полиномов Тейлора с 14 терминами, что, как я рассчитывал, было необходимо для оценки ошибки менее 1e-8. Однако я обнаружил, что это было быстрее,sin
чем рассчитыватьcos
, поэтому решил вместо этого рассчитатьcos
с помощьюcos=sqrt(1-sin^2)
Версия Python:
Версия Java:
источник
cos
рассчитываете излишне, я бы просто сделалsin(x+90degrees)
sin
как функцию и переменную. Я думал, что было бы быстрее не передавать что-то воsin()
второй раз, но я сравню их, чтобы увидеть, так ли это на самом деле. Было ли у вас впечатление, чтоcopySign()
функция медленнее, чем сложение, например, в моейsin()
функции?Октава (или Матлаб) & C
Немного сложный процесс сборки, но своего рода новый подход и результаты были обнадеживающими.
Подход заключается в создании аппроксимирующих квадратичных полиномов для каждой степени. Таким образом, степень = [0, 1), степень = [1, 2), ..., степень = [359, 360) будет иметь разные полиномы.
Октава - строительная часть
Октава общедоступна - Google
download octave
.Это определяет наиболее подходящий квадратичный полином для каждой степени.
Сохранить как
build-fast-trig.m
:C - строительная часть
Это преобразует дубликаты в текстовом формате в собственный двоичный формат в вашей системе.
Сохранить как
build-fast-trig.c
:Обобщение:
Генерация файла коэффициентов
Бегать:
Теперь у нас есть
qcoeffs.dat
файл данных для использования в реальной программе.C - быстрый триггер
Сохранить как
fast-trig.c
:Обобщение:
Бегать:
Он будет считывать
trig.in
, сохранятьtrig.out
и выводить на печать прошедшее время с точностью до миллисекунды.В зависимости от используемых методов тестирования может произойти сбой на определенных входных данных, например:
Правильный вывод должен быть
0.000000e+00 1.000000e+00 0.000000e+00
. Если результаты проверены с использованием строк, ввод не удастся, если они подтверждены с использованием абсолютной ошибки, напримерfabs(actual - result) < 1e-06
, ввод пройдет.Максимальная абсолютная ошибка для
sin
иcos
была ≤ 3e-07. Посколькуtan
результат не ограничен ± 1 и вы можете разделить относительно большое число на относительно небольшое число, абсолютная ошибка может быть больше. От -1 ≤ tan (x) ≤ +1 максимальная абсолютная ошибка была ≤ 4e-07. Для tan (x)> 1 и tan (x) <-1 максимальная относительная ошибка, например,fabs((actual - result) / actual)
обычно составляла <1e-06, пока вы не окажетесь в области (90 ± 5) или (270 ± 5) градусов, тогда ошибка ухудшается.В тестировании, среднее время на один вход был (1,053 ± 0,007) мкс, который на моей машине было около 0.070 мкс быстрее , чем родной
sin
иcos
,tan
определяется таким же образом.источник
кобра
Скомпилируйте это с
cobra filename -turbo
Тесты: AMD FX6300 с частотой 5,1 ГГц
Тест 360 * 10000, используемый ответом C, выполняется за 365 мс (против 190 мс)
Тест с 4 записями, используемый ответами Python и Java, выполняется за 0,32 мкс (против 30 мкс, 3 мкс)
Тест 1000 случайных углов, используемый ответом Фортрана, выполняется при 100 нс на угол (против 10 мкс)
источник
С
Вот моя попытка. Это работает так:
Постройте таблицу всех значений sin (x) от 0 до 450 градусов. Эквивалентно это все значения cos (x) от -90 до 360 градусов. С 2926 элементами достаточно места для значения каждые 1 / 6,5 градусов. Следовательно, программный блок составляет 1 / 6,5 градуса, а четверть оборота составляет 585 единиц.
Преобразовать входные градусы в программные единицы (умножить на
6.5==110.1 binary.
) Найти ближайшие значения для sin и cos из таблицы. затем преобразуйте оставшуюся часть ввода (дх) в радианы.Примените
sin(x+dx) == sin x +(d(sin x)/dx)*dx.
примечание формулы ,(d(sin x)/dx)==cos x,
но только если мы используем радианы.к сожалению, это не является достаточно точным само по себе, поэтому требуется другой термин, основанный на следующей производной.
d2(sin x)/dx2 == -sin x.
Это нужно умножить наdx*dx/2
(не уверен, откуда взялся коэффициент 2, но он работает.)Выполните аналогичную процедуру для
cos x
, затем рассчитайтеtan x == sin x / cos x
.Код
Здесь есть около 17 операций с плавающей запятой. Это может быть несколько улучшено. Программа содержит построение таблицы и вывод теста с использованием собственных функций триггера, но алгоритм этого не делает. Я добавлю синхронизацию и редактирование, чтобы соответствовать требованиям ввода-вывода позже (надеюсь, на этих выходных.) Он соответствует выводу встроенной функции, за исключением очень маленьких значений sin x и cos x, которые должны быть лучше, чем вывод исходной функции с некоторые настройки.
источник