2015-06-26 11 views
14

Następująca funkcja C pochodzi z projektu fastapprox.Dlaczego obciążenie wykładnicze IEEE-754 użyte w tym kodzie C wynosi 126.94269504 zamiast 127?

static inline float 
fasterlog2 (float x) 
{ 
    union { float f; uint32_t i; } vx = { x }; 
    float y = vx.i; 
    y *= 1.1920928955078125e-7f; 
    return y - 126.94269504f; 
} 

Czy niektórzy eksperci mogą tutaj wyjaśnić, dlaczego wykładnik potęgowania użyty w powyższym kodzie wynosi 126.94269504 zamiast 127? Czy jest to dokładniejsza wartość stronniczości?

+1

Compiler ostrzeżenie od 'y = vx.i unosić ; '" możliwa utrata danych ". –

+1

Dlaczego nie zapytać kogoś, kto to napisał? To naprawdę nie jest pytanie o kodowanie, to raczej pytanie o algorytm, prawda? – Dan

+1

@Dan - Tak, ale programiści C to tacy, którzy potrafią czytać kod C i zazwyczaj dbają o tak niskopoziomową wiedzę. Zgodnie z moim badaniem w Google, było już dużo projektów C za pomocą funkcji zaimplementowanych w fastapprox, więc może odpowiedzi na to pytanie są również przydatne dla programistów C. Jeszcze jedno, aby powiedzieć, dlaczego pytanie autora jest jedynym sposobem uzyskania odpowiedzi na pytanie? Tutaj mogę uzyskać szybsze odpowiedzi od różnych ekspertów. – Astaroth

Odpowiedz

9

W projekcie, który łączyłeś, zawierały one Mathematica notebook z wyjaśnieniem ich algorytmów, które zawierają "tajemniczą" wartość -126.94269.
Jeśli potrzebujesz przeglądarki, możesz ją bezpłatnie pobrać z telefonu Mathematica website.

Edytuj: Ponieważ jestem hojny, oto odpowiednia sekcja in screenshot form.

Mówiąc krótko, tłumaczą, że wartość jest "prostsza, szybsza i mniej dokładna".
Nie używasz -126.94269 zamiast -127, że używają go w miejsce wyniku następujących obliczeń (wartości zaokrąglone dla zwięzłość):

-124.2255 - 1.498 * mx - (1.72588/(0.35201 + mx)) 
+2

Uwielbiam to, że używają liczb 1.1920928955078125e-7 i 126.94269504, z dokładnością odpowiednio 17 i 11 cyfr, a następnie przyklejają 'f' na końcu, aby je unoszą! –

+0

@SteveSummit to 17 cyfr dziesiętnych; być może są one dokładnie reprezentowane w IEEE754 –

+0

@Mr_Llama, widzę, dziękuję bardzo. Okazuje się, że pośpiesznie czytałem ich stronę internetową. Nie zauważyłem, że istnieje taki notatnik Mathematica. – Astaroth

-4

Cóż, nie, 126.94269504 nie jest "bardziej dokładną" wartością odchylenia. Ten kod robi coś bardzo, bardzo dziwnego; Jestem całkiem zaskoczony, że w ogóle działa. Pobiera kawałki float, tak jakby były int (co z mojego doświadczenia zwykle daje ci totalną wartość śmieciową, ale może nie), następnie bierze tę wartość "śmieci" i zamienia ją z powrotem na float, następnie robi trochę matematyka na tym. Jest to, jak mówią, szybki i przybliżony sposób robienia czegoś, w tym przypadku, biorąc dziennik bazy 2. Nie powinno to w ogóle działać, ale różnica między 127 a 126.94269504 jest ewidentnie tylko jednym z kilku głupich czynników krówki, które mają na celu uratowanie jakiegoś znaczenia od tego, co powinno być bezsensownym kodem. (Rodzaj "dwóch prawie krzywd to coś prawie prawego").

Jeśli chcesz wyodrębnić dokładnie mantysę i wykładnik pływaka (choć to nie będzie ani tak szybkie, ani przybliżone), zwykły sposób to zrobić przy pomocy funkcji frexpf.

+4

-1; to nie śmieci, jeśli polegasz na określonym kodowaniu (a mianowicie [IEEE754] (https://en.wikipedia.org/wiki/Single-precision_floating-point_format)), a "trochę matematyki", które robi jest bardzo celowe. – MooseBoys

+3

Część wykładnicza liczby zmiennoprzecinkowej jest logarytmiczna, natomiast część mantysy jest liniowa. Kod wydaje się po prostu stosować liniowe przybliżenie najlepszego dopasowania, gdzie przesunięcie osi y równania liniowego jest połączone z tendencyjnością wykładnika. – njuffa

+2

To jednocześnie szalona i błyskotliwa technika. Jak już powiedziałem, jestem zaskoczony, że to działa, ale spróbowałem i widzę, że tak. Mogę nawet zrozumieć, jak to działa, w pewnym sensie, ale wynik końcowy nadal pozostawia mnie z uczuciem, och, nazywając "wolny" dwa razy na tym samym wskaźniku i mając go w przybliżeniu sortować moje dane dla mnie, czy coś! –

Powiązane problemy