Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Вычислить Sin и Cos (2 стр)

Вычислить Sin и Cos (2 стр)

Страницы: 1 2 3 48 Следующая »
Андрей5000Постоялецwww9 апр. 20189:58#15
Suslik
> ряды хорошо сходятся только в окрестности нуля.
Смотря какой ряд
eDmkУчастникwww9 апр. 201810:29#16
>Засрал весь кеш L1 и половину L2.
Таблицы спокойно сжимаются до 50 Кб. Точность 0.01. Так что не переживайте за кэш.
В моем случае кэша 25 Мб.
eDmkУчастникwww9 апр. 201811:04#17
>ряды хорошо сходятся только в окрестности нуля
Угу. Нормально сходятся. В 45° с точностью до 6 знаков. Мне в общем то 6 точных знаков хватает. Глюков нет.
eDmkУчастникwww9 апр. 201811:33#18
А вообще очень медленная функция получилась.
Может ее как оптимизировать можно? Или другой способ расчета?
+ Показать

Правка: 11 апр. 2018 11:20

SuslikМодераторwww9 апр. 201811:41#19
eDmk
порадовал расчёт факториалов за [cht]O(n^2)[/cht]

UPD: хотя углы в градусах, сравнение флотов и точки разрыва тоже здоровские. продолжай, пока всё нравится.

Правка: 9 апр. 2018 11:43

eDmkУчастникwww9 апр. 201813:20#20
Suslik
Да это просто проба пера. Стало интересно, вот и заморочился.
}:+()___ [Smile]Постоялецwww9 апр. 201813:58#21
eDmk
> Таблицы спокойно сжимаются до 50 Кб. Точность 0.01. Так что не переживайте за кэш.
> В моем случае кэша 25 Мб.
:facepalm:

50 Кб — это порядка размера кеша L1, 25 метров у тебя кеша L3, доступ к которому раз в 10 медленнее.
Я на таблице в несколько десятков значений делал точность 10−9, 0.01 — это просто смешно.
Простейшая формула имеет большую точность:

double sin_apx(double x)
{
    x /= 2 * pi;
    x -= round(x);
    x *= 7.59 * (0.5 - abs(x));
    return (1.634 + abs(x)) * x;
}

А вообще, тем про приблизительное вычисление тригонометрии уже было несколько штук.

DelfigamerПостоялецwww9 апр. 201814:21#22
0.
По-хорошему, полиномом нужно рисовать кривую на промежутке [0°; 90°], а остальные высчитывать через формулы приведения.
1.
> // Угол в градусах
> fY := (Y * RadToDegS);
По возможности, от промежуточных шагов следует избавляться, потому что, как правило, на каждую операцию тратится дополнительное время.
Поэтому вместо вот такого преобразования лучше изначально подобрать коэффициенты для расчёта в радианах и сэкономить на умножениях.
К тому же, конкретно в этой программе твои коэффициенты предназначены как раз для радианов, а не для градусов.
2.
> // Нормализация
> if (fY < 0.0) then
> fY := Abs(360.0 + fY);
Произвольные значения следует приводить с помощью деления с остатком.
3.
> // Граничные значения
Твой способ плох тем, что даёт резкие скачки значения. Вместо этого, следует подбирать изначальную кривую так, чтобы она плотно состыковывалась на концах.
Как следствие - разложение Тейлора на практике не применяется. Вместо этого, коэффициенты полинома подбирают так, чтобы кривая проходила через заранее заданные точки.
Допустим, мы хотим кривую, которая проходит через Изображение, Изображение, Изображение и Изображение. Поскольку здесь задано 4 точки, то из них мы можем подобрать 4 параметра, следовательно, искомый полином имеет вид
Изображение
Подставляя заданные точки в этот полином, получим линейную систему из 4-х уравнений, из которой найдём коэффициенты {a, b, c, d}. Их можно найти как числа, и эти числа можно скопировать в программу.
4.
> // Разложение ряда
Во-первых, сюда так же можно применить аргумент о промежуточных значениях. Поскольку нам известны все коэффициенты заранее, лучше рассчитать их где-нибудь отдельно и вписать в программу конечные числа, чем пересчитывать одно и то же при каждом вызове функции.
Во-вторых, значение полинома вида Изображение находят как Изображение, что позволяет опять-таки уменьшить число операций, а вместе с ним - и время работы функции.
5.
> // Значения меньше машинного эпсилона обнуляем
> if (Abs(Result) < SingleEpsilon)
> then Result := 0.0;
Если реализовать функцию через повторения одной кривой, как я описал в начале, то функция будет приближаться к нулю только возле нуля аргумента, и будет делать это точно. Как следствие, резкий перепад от этого условия скорее навредит, чем принесёт пользу.

Правка: 9 апр. 2018 16:01

foxesПостоялецwww9 апр. 201814:31#23
}:+()___ [Smile]
> 50 Кб — это порядка размера кеша L1, 25 метров у тебя кеша L3, доступ к
> которому раз в 10 медленнее.
Не плачь, даже интел в свою либу кучу таблиц напихал, в том числе и с синусами, каждая не менее 2-4 кило.

Правка: 9 апр. 2018 14:36

eDmkУчастникwww9 апр. 201814:31#24
}:+()___ [Smile]

Ваш синус (видео):

+ Показать

Мой косинус (видео):

+ Показать

Я без претензий :)

eDmkУчастникwww9 апр. 201814:37#25
>Не плачь, даже интел в свою либу кучу таблиц напихал
Да я не плачу. Даже в ZX Spectrum таблицы были.
https://albertveli.wordpress.com/2015/01/10/zx-sine/
foxesПостоялецwww9 апр. 201814:38#26
eDmk
> ZX Spectrum
а я знаю, сам туда пихал, и ответ не тебе.
DelfigamerПостоялецwww9 апр. 201815:54#27
eDmk
> Ваш синус (видео):
Я не знаю, какой синус ты туда вписал, но это точно не синус Смайла.
Перепроверь ещё раз, ты явно где-то ошибся.

Правка: 9 апр. 2018 15:54

eDmkУчастникwww9 апр. 201817:30#28
>Перепроверь ещё раз, ты явно где-то ошибся.
Вот тут рабочий вариант кода:
http://rextester.com/DALIFZ95838

Отклонение 0.0011 Это очень много.
У меня отклонение начинаются с 7-го знака после запятой.
И кстати я нигде не ошибся при переводе на Pascal.
Таблицы идентичные. Отклонения идентичные.

Правка: 9 апр. 2018 17:44

AslanПостоялецwww9 апр. 201819:03#29
eDmk
> Sin A = X/Radius, Cos A = Y/Radius
> как получить величину X и Y, если известен только угол?
X = Radius * sin(A)
Y = Radius * cos(A)
Никак, надо еще знать Radius

Правка: 9 апр. 2018 19:03

Страницы: 1 2 3 48 Следующая »

/ Форум / Программирование игр / Общее

2001—2018 © GameDev.ru — Разработка игр