2015-06-26 15 views
14

Aşağıdaki C işlevi fastapprox projesinden alınmıştır.Bu C kodunda kullanılan IEEE-754 üssü öneki değeri 127 yerine 126.94269504 olur?

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

burada bazı uzmanlar yukarıdaki kodu kullanılan üs önyargı 126,94269504 yerine 127 neden açıklayabilir misiniz? Daha doğru önyargı değeri mi?

+1

derleyici uyarı 'y yüzer = vx.i “olası veri kaybı”. –

+1

Neden onu yazan birisine sormuyorsunuz? Bu gerçekten bir kodlama sorusu değil, daha çok bir algoritma sorusu, değil mi? – Dan

+1

@Dan - Evet, fakat C geliştiricileri C kodunu okuyan kişilerdir ve genellikle düşük seviyeli bir bilgiyle ilgilenirler. Benim googlingime göre, fastapprox'ta uygulanan fonksiyonları kullanan çok sayıda C projesi var, bu yüzden bu sorunun cevabı C geliştiricileri için de yararlıdır. Bir tane daha söylemek gerekirse, neden yazarın sorusunu cevaplamanın tek yolu cevaplandırıyor? Burada farklı uzmanlardan daha hızlı yanıtlar alabiliyorum. – Astaroth

cevap

9

Bağladığınız projede, "gizemli" -126.94269 değerini içeren algoritmalarının açıklamasıyla birlikte bir Mathematica notebook eklediler.
İzleyiciye ihtiyacınız varsa, ücretsiz olarak Mathematica website'dan bir tane alabilirsiniz.

Düzenleme: Cömert olduğum için ilgili bölüm in screenshot form.

Basitçe ifade edersek, değerin "daha basit, daha hızlı ve daha az doğru" olduğunu açıklarlar. Bunlar -127 yerine -126.94269 kullanılarak değil
, bunlar (değerler kısalık için yuvarlanmış) aşağıdaki hesaplama sonucunun yerde kullanırken:

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

Numaraları 1.1920928955078125e-7 ve 126.94269504 sayılarını sırasıyla 17 ve 11 basamak değerinde hassasiyetle kullandıklarını ve daha sonra bir “f” harfi çaktıklarını yaptıklarını seviyorum! –

+0

@SteveSummit, 17 ondalık basamaktır; belki de tam olarak IEEE754 –

+0

@Mr_Llama'da temsil edilebilirler, görüyorum, çok teşekkür ederim. Aceleyle kendi web sitelerini okuyordum. Böyle bir Mathematica Defterinin olduğunu fark etmedim. – Astaroth

-4

Eh, 126.94269504, "daha doğru" bir önyargı değeri değil. Bu kod çok garip bir şey yapıyor; Oldukça şaşırdığını hiç işe yaramıyor. Bir floatın bitlerini sanki bir int (benim tecrübemde size tamamen çöp değeri verir, ama belki de değil) alır, sonra o "çöp" int değerini alır ve bir float'a geri dönüştürür. üzerinde matematik. Bu, dedikleri gibi, bir şey yapmanın hızlı ve yaklaşık bir yoludur, bu durumda, taban-2 logunu alırlar. Hiç işe yaramaz, ama 127 ile 126.94269504 arasındaki fark, anlamsız bir kod olması gereken bir şeyden kurtulmayı amaçlayan birkaç goofy fudge faktöründen sadece bir tanesidir. ("Neredeyse iki kez yanlış yazılmış bir şey", "hemen hemen doğru" türden bir şeydir.)

Bir floatın mantısını ve üssünü tam olarak çıkarmak isterseniz (bu hızlı veya yaklaşık olarak aynı olmayabilir), Bunu yapmak için normal yolu frexpf işleviyle.

+4

-1; Belli bir kodlamaya güveniyorsanız (yani [IEEE754] (https://en.wikipedia.org/wiki/Single-precision_floating-point_format)) ve "biraz matematik" yapması çok kasıtlı değildir. – MooseBoys

+3

Kayan nokta sayısının üs kısmı, mantis parçası doğrusal iken, logaritmiktir. Kod, lineer denklemin y ekseni ofsetinin, üssel önyargı ile birleştirildiği doğrusal en iyi uyum yaklaşımını uygulamaktadır. – njuffa

+2

Aynı anda bir deli ve mükemmel bir tekniktir. Söylediğim gibi şaşırıyorum, ama ben denedim ve bunu görebiliyorum. Nasıl çalıştığını bile anlayabiliyorum, bir çeşit, ama sonuç hala beni hala bir his ile terk ediyor, oh, aynı işaretçiye iki defa 'free' deniyor ve bu da benim verilerimi neredeyse benim için mi yoksa bir şey mi yapıyor? –