Przeglądałem dezasemblacje .NET i kod źródłowy GCC, ale wydaje się, że nigdzie nie mogę znaleźć faktycznej implementacji sin()
i innych funkcji matematycznych ... zawsze wydają się odnosić do czegoś innego.
Czy ktoś może mi pomóc je znaleźć? Wydaje mi się, że jest mało prawdopodobne, aby WSZYSTKIE urządzenia, na których będzie działał C, wspierały funkcje wyzwalające w sprzęcie, więc musi być gdzieś algorytm oprogramowania , prawda?
Zdaję sobie sprawę z kilku sposobów, które funkcje mogą być obliczone i pisało własne procedury do obliczania funkcji wykorzystujących szereg Taylora dla zabawy. Ciekawi mnie, jak robią to prawdziwe języki produkcyjne, ponieważ wszystkie moje implementacje są zawsze o kilka rzędów wielkości wolniejsze, chociaż uważam, że moje algorytmy są dość sprytne (oczywiście nie są).
źródło
Odpowiedzi:
W GNU libm implementacja
sin
zależy od systemu. Dlatego implementację można znaleźć dla każdej platformy, gdzieś w odpowiednim podkatalogu sysdeps .Jeden katalog zawiera implementację w C, wniesioną przez IBM. Od października 2011 r. Jest to kod, który faktycznie działa, gdy wywołujesz
sin()
typowy system Linux x86-64. Jest najwyraźniej szybszy niżfsin
instrukcja montażu. Kod źródłowy: sysdeps / ieee754 / dbl-64 / s_sin.c , poszukaj__sin (double x)
.Ten kod jest bardzo złożony. Żaden algorytm programowy nie jest tak szybki, jak to możliwe, a także dokładny w całym zakresie wartości x , więc biblioteka implementuje kilka różnych algorytmów, a jego pierwszym zadaniem jest przyjrzenie się x i zdecydowanie, którego algorytmu użyć.
Gdy x jest bardzo bardzo bliskie zeru,
sin(x) == x
jest właściwą odpowiedzią.Nieco dalej
sin(x)
wykorzystuje znaną serię Taylor. Jest to jednak dokładne tylko w pobliżu 0, więc ...Gdy kąt jest większy niż około 7 °, stosuje się inny algorytm, obliczając przybliżenia szeregów Taylora zarówno dla sin (x), jak i cos (x), a następnie używając wartości ze wstępnie obliczonej tabeli w celu uściślenia przybliżenia.
Kiedy | x | > 2, żaden z powyższych algorytmów nie działałby, więc kod zaczyna się od obliczenia wartości bliższej 0, którą można podać
sin
lubcos
zamiast niej.Jest jeszcze jedna gałąź, w której x jest NaN lub nieskończonością.
W tym kodzie wykorzystano kilka numerycznych hacków, których nigdy wcześniej nie widziałem, choć dla wszystkich wiem, że mogą być dobrze znane wśród ekspertów zmiennoprzecinkowych. Czasami wyjaśnienie wymaga kilku wierszy kodu. Na przykład te dwie linie
są używane (czasami) w zmniejszaniu x do wartości bliskiej 0, która różni się od x wielokrotnością π / 2, a konkretnie
xn
× π / 2. Sposób, w jaki odbywa się to bez podziału lub rozgałęzienia, jest dość sprytny. Ale w ogóle nie ma komentarza!Starsze 32-bitowe wersje GCC / glibc korzystały z
fsin
instrukcji, która jest zaskakująco niedokładna w przypadku niektórych danych wejściowych. Jest fascynujący post na blogu ilustrujący to za pomocą zaledwie 2 linii kodu .Implementacja fdlibm
sin
w czystym C jest znacznie prostsza niż glibc i jest ładnie komentowana. Kod źródłowy: fdlibm / s_sin.c i fdlibm / k_sin.cźródło
sin()
; wpiszgdb a.out
, abreak sin
następnierun
, a następniedisassemble
.__kernel_sin
jest jednak zdefiniowany w k_sin.c i jest czysty C. Kliknij go jeszcze raz - za pierwszym razem spartaczyłem adres URL.Funkcje takie jak sinus i cosinus są zaimplementowane w mikrokodzie wewnątrz mikroprocesorów. Na przykład układy Intel mają instrukcje montażu. Kompilator prądu przemiennego wygeneruje kod wywołujący instrukcję montażu. (W przeciwieństwie do tego kompilator Java nie. Java ocenia funkcje triggera w oprogramowaniu, a nie w sprzęcie, dlatego działa znacznie wolniej.)
Chipy nie używają szeregów Taylora do obliczania funkcji triggera, przynajmniej nie do końca. Przede wszystkim używają CORDIC , ale mogą również użyć krótkiej serii Taylora, aby dopracować wynik CORDIC lub w szczególnych przypadkach, takich jak obliczenie sinusoidy z wysoką względną dokładnością dla bardzo małych kątów. Aby uzyskać więcej wyjaśnień, zobacz odpowiedź StackOverflow .
źródło
OK dzieciaki, czas na profesjonalistów ... To jedna z moich największych skarg z niedoświadczonymi inżynierami oprogramowania. Przychodzą one do obliczania funkcji transcendentalnych od zera (przy użyciu serii Taylora), tak jakby nikt nigdy wcześniej nie dokonywał tych obliczeń w swoim życiu. Nie prawda. Jest to dobrze zdefiniowany problem, do którego tysiące razy podchodzili bardzo sprytni inżynierowie oprogramowania i sprzętu i ma dobrze zdefiniowane rozwiązanie. Zasadniczo większość funkcji transcendentalnych korzysta z wielomianów Czebyszewa do ich obliczania. To, które wielomiany są stosowane, zależy od okoliczności. Po pierwsze, Biblia na ten temat jest książką Hart and Cheney zatytułowaną „Computer Approximations”. W tej książce możesz zdecydować, czy masz sumator sprzętowy, mnożnik, dzielnik itp. I zdecydować, które operacje są najszybsze. np. jeśli miałeś naprawdę szybki dzielnik, najszybszym sposobem obliczenia sinusa może być P1 (x) / P2 (x), gdzie P1, P2 to wielomiany Czebyszewa. Bez szybkiego dzielnika może to być po prostu P (x), gdzie P ma znacznie więcej terminów niż P1 lub P2 .... więc byłoby wolniej. Pierwszym krokiem jest więc określenie sprzętu i jego możliwości. Następnie wybierasz odpowiednią kombinację wielomianów Czebiszewa (zwykle ma postać cos (ax) = aP (x) na przykład dla cosinusa, ponownie, gdzie P jest wielomianem Czebyszewa). Następnie decydujesz, jakiej precyzji dziesiętnej chcesz. np. jeśli chcesz precyzji 7 cyfr, spójrz na to w odpowiedniej tabeli we wspomnianej książce i da ci (dla precyzji = 7,33) liczbę N = 4 i wielomian 3502. N jest rzędu wielomian (więc jest to p4.x ^ 4 + p3.x ^ 3 + p2.x ^ 2 + p1.x + p0), ponieważ N = 4. Następnie sprawdzasz rzeczywistą wartość p4, p3, p2, p1, wartości p0 z tyłu książki poniżej 3502 (będą w liczbach zmiennoprzecinkowych). Następnie implementujesz swój algorytm w oprogramowaniu w postaci: (((p4.x + p3) .x + p2) .x + p1) .x + p0 .... i tak obliczysz cosinus do 7 miejsc po przecinku miejsca na tym sprzęcie.
Zauważ, że większość sprzętowych implementacji operacji transcendentalnych w FPU zwykle wymaga jakiegoś mikrokodu i podobnych operacji (zależy od sprzętu). Wielomiany Czebyszewa są używane w przypadku większości transcendentałów, ale nie wszystkich. Np. pierwiastek kwadratowy jest szybszy w użyciu podwójnej iteracji metody Newtona raphsona przy użyciu najpierw tabeli odnośników. Znów powie ci to książka „Computer Approximations”.
Jeśli planujesz wdrożyć te funkcje, polecam każdemu, aby otrzymał kopię tej książki. To naprawdę Biblia dla tego rodzaju algorytmów. Zauważ, że istnieją wiązki alternatywnych sposobów obliczania tych wartości, takich jak cordics itp., Ale zwykle są one najlepsze dla określonych algorytmów, w których potrzebujesz tylko niskiej precyzji. Aby zagwarantować precyzję za każdym razem, wielomian Czebyszewa jest właściwą drogą. Tak jak powiedziałem, dobrze zdefiniowany problem. Został rozwiązany od 50 lat ... i tak to się robi.
To powiedziawszy, istnieją techniki, dzięki którym wielomiany Czebyszewa mogą być użyte do uzyskania pojedynczej precyzji wyniku z wielomianem niskiego stopnia (jak przykład dla cosinusa powyżej). Następnie istnieją inne techniki interpolacji między wartościami w celu zwiększenia dokładności bez konieczności przechodzenia do znacznie większego wielomianu, takie jak „metoda dokładnych tabel Gal”. Ta ostatnia technika odnosi się do postu odnoszącego się do literatury ACM. Ale ostatecznie wielomian Czebeszewa służy do uzyskania 90% drogi.
Cieszyć się.
źródło
W
sin
szczególności użycie rozszerzenia Taylor dałoby ci:sin (x): = x - x ^ 3/3! + x ^ 5/5! - x ^ 7/7! + ... (1)
dodawałeś terminy, dopóki różnica między nimi nie będzie niższa niż akceptowany poziom tolerancji lub tylko na skończoną liczbę kroków (szybciej, ale mniej precyzyjnie). Przykładem może być coś takiego:
Uwaga: (1) działa z powodu aproksymacji sin (x) = x dla małych kątów. W przypadku większych kątów musisz obliczyć coraz więcej terminów, aby uzyskać akceptowalne wyniki. Możesz użyć argumentu while i kontynuować dla pewnej dokładności:
źródło
Tak, istnieją algorytmy programowe do obliczania
sin
. Zasadniczo obliczanie tego rodzaju rzeczy za pomocą komputera cyfrowego jest zwykle wykonywane przy użyciu metod numerycznych, takich jak aproksymacja szeregu Taylora reprezentującego funkcję.Metody numeryczne mogą aproksymować funkcje z dowolną dokładnością, a ponieważ dokładność, którą masz w liczbach zmiennoprzecinkowych, jest skończona, całkiem dobrze nadają się do tych zadań.
źródło
Użyj serii Taylora i spróbuj znaleźć relację między terminami serii, aby nie obliczać rzeczy raz po raz
Oto przykład dla cosinusa:
używając tego możemy uzyskać nowy warunek sumy używając już używanego (unikamy silni i x 2p )
źródło
To złożone pytanie. Procesor podobny do Intela z rodziny x86 ma sprzętową implementację tej
sin()
funkcji, ale jest częścią FPU x87 i nie jest już używany w trybie 64-bitowym (zamiast tego używane są rejestry SSE2). W tym trybie używana jest implementacja oprogramowania.Istnieje kilka takich wdrożeń. Jeden jest w fdlibm i jest używany w Javie. O ile mi wiadomo, implementacja glibc zawiera części fdlibm i inne części dostarczone przez IBM.
Implementacje programowe funkcji transcendentalnych, takie jak
sin()
zwykle wykorzystują aproksymacje wielomianami, często uzyskiwane z serii Taylora.źródło
sin
icos
są szybsze niż instrukcje sprzętowe na FPU. Prostsze, bardziej naiwne biblioteki zwykle używają instrukcjifsin
ifcos
.FSIN
pełnej precyzji. Byłbym bardzo wdzięczny, gdybyś podał mi nazwy tych szybkich bibliotek, ciekawe jest zajrzeć.sin()
jest około dwa razy szybsza niż to, cofsin
oblicza (właśnie dlatego, że odbywa się to z mniejszą precyzją). Zauważ, że x87 ma nieco mniej dokładną dokładność niż zapowiadane 79 bitów.Wielomiany Czebyszewa, jak wspomniano w innej odpowiedzi, to wielomiany, w których największa różnica między funkcją a wielomianem jest jak najmniejsza. To doskonały początek.
W niektórych przypadkach maksymalny błąd nie jest tym, co Cię interesuje, ale maksymalny błąd względny. Na przykład dla funkcji sinus, błąd w pobliżu x = 0 powinien być znacznie mniejszy niż dla większych wartości; chcesz mały błąd względny . Obliczymy zatem wielomian Czebiszewa dla sin x / x i pomnożymy ten wielomian przez x.
Następnie musisz dowiedzieć się, jak ocenić wielomian. Chcesz to ocenić w taki sposób, że wartości pośrednie są małe, a zatem błędy zaokrąglania są małe. W przeciwnym razie błędy zaokrąglania mogą stać się znacznie większe niż błędy wielomianu. A w przypadku funkcji takich jak funkcja sinusoidalna, jeśli jesteś nieostrożny, może się zdarzyć, że wynik obliczony dla sin x będzie większy niż wynik dla sin y, nawet gdy x <y. Potrzebny jest więc ostrożny wybór kolejności obliczeń i obliczanie górnych granic błędu zaokrąglania.
Na przykład sin x = x - x ^ 3/6 + x ^ 5/120 - x ^ 7/5040 ... Jeśli naiwnie obliczysz sin x = x * (1 - x ^ 2/6 + x ^ 4 / 120 - x ^ 6/5040 ...), wówczas funkcja w nawiasach maleje i stanie się tak, że jeśli y będzie następną większą liczbą od x, to czasami sin y będzie mniejszy niż sin x. Zamiast tego obliczyć sin x = x - x ^ 3 * (1/6 - x ^ 2/120 + x ^ 4/5040 ...) tam, gdzie to nie może się zdarzyć.
Obliczając wielomiany Czebyszewa, zwykle trzeba na przykład zaokrąglić współczynniki do podwójnej precyzji. Ale chociaż wielomian Czebyszewa jest optymalny, wielomian Czebyszewa o współczynnikach zaokrąglonych do podwójnej precyzji nie jest optymalnym wielomianem o współczynnikach podwójnej precyzji!
Na przykład dla sin (x), gdzie potrzebujesz współczynników dla x, x ^ 3, x ^ 5, x ^ 7 itd., Wykonaj następujące czynności: Oblicz najlepsze przybliżenie sin x wielomianem (ax + bx ^ 3 + cx ^ 5 + dx ^ 7) z wyższą niż podwójna precyzja, a następnie zaokrąglamy a do podwójnej precyzji, dając A. Różnica między a i A byłaby dość duża. Teraz obliczyć najlepsze przybliżenie (sin x - Ax) za pomocą wielomianu (bx ^ 3 + cx ^ 5 + dx ^ 7). Otrzymujesz różne współczynniki, ponieważ dostosowują się one do różnicy między a i A. Okrąg b do podwójnej precyzji B. Następnie przybliż (sin x - Ax - Bx ^ 3) za pomocą wielomianu cx ^ 5 + dx ^ 7 i tak dalej. Otrzymasz wielomian, który jest prawie tak dobry, jak oryginalny wielomian Czebeszewa, ale znacznie lepszy niż Czebyshev zaokrąglony do podwójnej precyzji.
Następnie należy wziąć pod uwagę błędy zaokrąglania przy wyborze wielomianu. Znalazłeś wielomian z minimalnym błędem w wielomianu ignorującym błąd zaokrąglania, ale chcesz zoptymalizować wielomian plus błąd zaokrąglania. Po uzyskaniu wielomianu Czebyszewa można obliczyć granice błędu zaokrąglania. Powiedz, że f (x) to twoja funkcja, P (x) to wielomian, a E (x) to błąd zaokrąglania. Nie chcesz optymalizować | f (x) - P (x) |, chcesz zoptymalizować | f (x) - P (x) +/- E (x) | Otrzymasz nieco inny wielomian, który próbuje utrzymać błędy wielomianu na dole tam, gdzie błąd zaokrąglania jest duży, i nieco rozluźnia błędy wielomianu, gdy błąd zaokrąglania jest mały.
Wszystko to pozwoli ci łatwo zaokrąglić błędy co najwyżej 0,55 razy ostatni bit, gdzie +, -, *, / mają błędy zaokrąglenia co najwyżej 0,50 razy ostatni bit.
źródło
Jeśli chodzi o funkcje trygonometryczne jak
sin()
,cos()
,tan()
nie było wzmianki, po 5 latach, ważnego aspektu wysokiej jakości funkcji trygonometrycznych: redukcją zasięgu .Wczesnym krokiem każdej z tych funkcji jest zmniejszenie kąta w radianach do zakresu 2 * π. Ale π jest nieracjonalne, więc proste redukcje, takie jak
x = remainder(x, 2*M_PI)
wprowadzenie błędu asM_PI
, lub maszyna pi, są przybliżeniem π. Jak to zrobićx = remainder(x, 2*π)
?Wczesne biblioteki korzystały z rozszerzonej precyzji lub spreparowanego programowania, aby dawać wysokiej jakości wyniki, ale nadal w ograniczonym zakresie
double
. Gdy zażądano dużej wartościsin(pow(2,30))
, wyniki były bez znaczenia lub0.0
być może z flagą błędu ustawioną na coś takiego jakTLOSS
całkowita utrata precyzji lubPLOSS
częściowa utrata precyzji.Dobra redukcja dużych wartości do przedziału, takiego jak -π do π, stanowi trudny problem, który rywalizuje z wyzwaniami podstawowej funkcji trig, jak
sin()
sama w sobie.Dobrym raportem jest redukcja argumentów w przypadku ogromnych argumentów: dobry do ostatniego kawałka (1992). Dobrze obejmuje ten problem: omawia potrzebę i sposób działania na różnych platformach (SPARC, PC, HP, 30+ i inne) i zapewnia algorytm rozwiązania, który daje wyniki jakościowe dla wszystkich
double
od-DBL_MAX
doDBL_MAX
.Jeśli oryginalne argumenty są wyrażone w stopniach, ale mogą mieć dużą wartość, użyj
fmod()
najpierw dla zwiększenia precyzji. Dobrafmod()
nie wprowadzi żadnego błędu, a zatem zapewni doskonałe zmniejszenie zasięgu.Różne tożsamości wyzwalaczy i
remquo()
oferują jeszcze więcej ulepszeń. Przykład: sind ()źródło
Rzeczywista implementacja funkcji bibliotecznych zależy od konkretnego kompilatora i / lub dostawcy biblioteki. Niezależnie od tego, czy odbywa się to sprzętowo, czy programowo, niezależnie od tego, czy jest to rozszerzenie Taylora, czy nie, itd.
Zdaję sobie sprawę, że to absolutnie nie pomoże.
źródło
Zazwyczaj są one zaimplementowane w oprogramowaniu i w większości przypadków nie będą używać odpowiednich wywołań sprzętowych (czyli tak zwanych). Jednak, jak zauważył Jason, są one specyficzne dla implementacji.
Zauważ, że te procedury oprogramowania nie są częścią źródeł kompilatora, ale raczej można je znaleźć w bibliotece odpowiadającej kodowania, takiej jak clib lub glibc dla kompilatora GNU. Zobacz http://www.gnu.org/software/libc/manual/html_mono/libc.html#Trig-Functions
Jeśli chcesz mieć większą kontrolę, powinieneś dokładnie ocenić, czego dokładnie potrzebujesz. Niektóre z typowych metod to interpolacja tabel przeglądowych, wywołanie asemblera (które często jest wolne) lub inne schematy aproksymacji, takie jak Newton-Raphson dla pierwiastków kwadratowych.
źródło
Jeśli potrzebujesz implementacji w oprogramowaniu, a nie w sprzęcie, miejscem, w którym można znaleźć ostateczną odpowiedź na to pytanie, jest rozdział 5 przepisów numerycznych . Moja kopia jest w pudełku, więc nie mogę podać szczegółów, ale krótka wersja (jeśli dobrze to pamiętam) polega na tym, że bierzesz
tan(theta/2)
za swoją prymitywną operację i obliczasz pozostałe stamtąd. Obliczenia są wykonywane z aproksymacją serii, ale jest to coś, co zbiega się znacznie szybciej niż seria Taylora.Przepraszam, że nie mogę zapamiętać więcej, nie wspierając książki.
źródło
Nie ma nic lepszego niż trafienie do źródła i zobaczenie, jak ktoś to zrobił w powszechnie używanej bibliotece; spójrzmy w szczególności na jedną implementację biblioteki C. Wybrałem uLibC.
Oto funkcja grzechu:
http://git.uclibc.org/uClibc/tree/libm/s_sin.c
który wygląda na to, że obsługuje kilka specjalnych przypadków, a następnie dokonuje pewnej redukcji argumentów, aby odwzorować dane wejściowe na zakres [-pi / 4, pi / 4], (dzielenie argumentu na dwie części, dużą część i ogon) przed dzwonieniem
http://git.uclibc.org/uClibc/tree/libm/k_sin.c
który następnie działa na tych dwóch częściach. Jeśli nie ma ogona, przybliżona odpowiedź jest generowana przy użyciu wielomianu stopnia 13. Jeśli istnieje ogon, otrzymujesz niewielki dodatek korygujący oparty na zasadzie, że
sin(x+y) = sin(x) + sin'(x')y
źródło
Ilekroć taka funkcja jest oceniana, wówczas na pewnym poziomie najprawdopodobniej istnieje:
Jeśli nie ma wsparcia sprzętowego, kompilator prawdopodobnie używa tej drugiej metody, emitując tylko kod asemblera (bez symboli debugowania), zamiast używać biblioteki ac --- co utrudnia śledzenie rzeczywistego kodu w debuggerze.
źródło
Jak zauważyło wiele osób, zależy to od wdrożenia. Ale o ile rozumiem twoje pytanie, byłeś zainteresowany rzeczywistą implementacją oprogramowania funkcji matematycznych, ale po prostu nie udało ci się go znaleźć. Jeśli tak jest, to tutaj jesteś:
dosincos.c
znajdujący się w rozpakowanym folderze głównym \ sysdeps \ ieee754 \ dbl-64 glibcMożesz także zajrzeć do plików z
.tbl
rozszerzeniem, ich zawartość to nic innego jak ogromne tabele wstępnie obliczonych wartości różnych funkcji w formie binarnej. Właśnie dlatego implementacja jest tak szybka: zamiast obliczać wszystkie współczynniki z jakiejkolwiek serii, której używają, po prostu dokonują szybkiego wyszukiwania, co jest znacznie szybsze. BTW, używają serii Tailor do obliczania sinusa i cosinusa.Mam nadzieję, że to pomoże.
źródło
Spróbuję odpowiedzieć na przypadek
sin()
programu C skompilowanego z kompilatorem C GCC na bieżącym procesorze x86 (powiedzmy Intel Core 2 Duo).W języku C Standard C Library zawiera typowych funkcji matematycznych, nie ujęte w samym języku (np
pow
,sin
icos
dla władzy, sinus i cosinus, odpowiednio). Nagłówki są zawarte w matematyce . H.Obecnie w systemie GNU / Linux funkcje bibliotek są dostarczane przez glibc (GNU libc lub GNU C Library). Ale kompilator GCC chce, abyś łączył się z biblioteką matematyczną (
libm.so
) przy użyciu-lm
flagi kompilatora, aby umożliwić korzystanie z tych funkcji matematycznych.Nie jestem pewien, dlaczego nie jest częścią standardowej biblioteki C.Byłaby to wersja oprogramowania funkcji zmiennoprzecinkowych lub „soft-float”.Poza tym: Powód oddzielenia funkcji matematycznych jest historyczny i miał na celu jedynie zmniejszenie wielkości programów wykonywalnych w bardzo starych systemach uniksowych, być może zanim udostępnione biblioteki będą dostępne, o ile mi wiadomo.
Teraz kompilator może zoptymalizować standardową funkcję biblioteki C
sin()
(dostarczoną przezlibm.so
), aby zastąpić ją wywołaniem instrukcji natywnej do wbudowanej funkcji sin () procesora / FPU, która istnieje jako instrukcja FPU (FSIN
dla x86 / x87) na nowsze procesory, takie jak seria Core 2 (jest to poprawne już od czasów i486DX). Zależy to od flag optymalizacji przekazywanych do kompilatora gcc. Gdyby kompilatorowi nakazano napisać kod, który byłby wykonywany na dowolnym procesorze i386 lub nowszym, nie dokonałby takiej optymalizacji.-mcpu=486
Flag kompilatora by poinformować, że to bezpieczne, aby dokonać takiej optymalizacji.Teraz, jeśli program wykonałby wersję oprogramowania funkcji sin (), zrobiłby to w oparciu o algorytm CORDIC (komputer cyfrowy z rotacją współrzędnych) lub BKM , lub bardziej prawdopodobne jest obliczenie tabeli lub szeregu mocy, które jest obecnie powszechnie używane do obliczania takie funkcje transcendentalne. [Src: http://en.wikipedia.org/wiki/Cordic#Application]
Każda najnowsza (od około 2,9x) wersja gcc oferuje również wbudowaną wersję sin,
__builtin_sin()
która zostanie użyta do zastąpienia standardowego wywołania do wersji biblioteki C, jako optymalizacja.Jestem pewien, że jest to jasne jak błoto, ale mam nadzieję, że dostarczy ci więcej informacji, niż się spodziewałeś, i wiele skoków do punktów, aby dowiedzieć się więcej.
źródło
Jeśli chcesz spojrzeć na faktyczną implementację GNU tych funkcji w C, sprawdź najnowszy pakiet glibc. Zobacz biblioteka GNU C .
źródło
Nie używaj serii Taylor. Wielomiany Czebyszewa są zarówno szybsze, jak i dokładniejsze, jak wskazało kilka osób powyżej. Oto implementacja (oryginalnie z ZX Spectrum ROM): https://albertveli.wordpress.com/2015/01/10/zx-sine/
źródło
Obliczanie sinus / cosinus / tangens jest w rzeczywistości bardzo łatwe do zrobienia za pomocą kodu za pomocą serii Taylora. Samo napisanie zajmuje około 5 sekund.
Cały proces można podsumować za pomocą tego równania:
Oto kilka procedur, które napisałem dla C:
źródło
Poprawiona wersja kodu z odpowiedzi Blindy
źródło
Istota tego, jak to robi, leży w tym fragmencie Applied Numerical Analysis Geralda Wheatleya:
Kilka punktów, o których należy wspomnieć powyżej, to fakt, że niektóre algorytmy faktycznie interpolują dane z tabeli, chociaż tylko dla kilku pierwszych iteracji. Zwróć też uwagę na to, jak wspomniano, że komputery używają wielomianów aproksymacyjnych bez określania, jaki typ wielomianu aproksymacyjnego. Jak zauważyli inni w wątku, wielomiany Czebyszewa są w tym przypadku bardziej wydajne niż wielomiany Taylora.
źródło
jeśli chcesz,
sin
tojeśli chcesz,
cos
tojeśli chcesz,
sqrt
towięc po co używać niedokładnego kodu, gdy zrobią to instrukcje maszyny?
źródło