![](/img/trans.png)
[英]Is there a floating point literal suffix in C++ to make a number double precision?
[英]Implementing a half precision floating point number in C++
我試圖實現一種簡單的半精度浮點類型,完全出於存儲目的(無算術,隱式轉換為double),但是我得到了奇怪的行為。 我在-0.5到0.5之間得到完全錯誤的Half
值。 我也得到討厭的“偏移”值,例如0.8被解碼為0.7998。
我是C ++的新手,如果您能指出我的錯誤並幫助我稍微提高一點精度,那將是很棒的。 我也很好奇這個解決方案的便攜性。 謝謝!
這是輸出-雙精度值和一半的實際解碼值:
-1 -1
-0.9 -0.899902
-0.8 -0.799805
-0.7 -0.699951
-0.6 -0.599854
-0.5 -0.5
-0.4 -26208
-0.3 -19656
-0.2 -13104
-0.1 -6552
-1.38778e-16 -2560
0.1 6552
0.2 13104
0.3 19656
0.4 26208
0.5 32760
0.6 0.599854
0.7 0.699951
0.8 0.799805
0.9 0.899902
這是到目前為止的代碼:
#include <stdint.h>
#include <cmath>
#include <iostream>
using namespace std;
#define EXP 4
#define SIG 11
double normalizeS(uint v) {
return (0.5f * v / 2048 + 0.5f);
}
uint normalizeP(double v) {
return (uint)(2048 * (v - 0.5f) / 0.5f);
}
class Half {
struct Data {
unsigned short sign : 1;
unsigned short exponent : EXP;
unsigned short significant : SIG;
};
public:
Half() {}
Half(double d) { loadFromFloat(d); }
Half & operator = (long double d) {
loadFromFloat(d);
return *this;
}
operator double() {
long double sig = normalizeS(_d.significant);
if (_d.sign) sig = -sig;
return ldexp(sig, _d.exponent /*+ 1*/);
}
private:
void loadFromFloat(long double f) {
long double v;
int exp;
v = frexp(f, &exp);
v < 0 ? _d.sign = 1 : _d.sign = 0;
_d.exponent = exp/* - 1*/;
_d.significant = normalizeP(fabs(v));
}
Data _d;
};
int main() {
Half a[255];
double d = -1;
for (int i = 0; i < 20; ++i) {
a[i] = d;
cout << d << " " << a[i] << endl;
d += 0.1;
}
}
我最終得到了一個非常簡單(真的很簡單)的解決方案,能夠表示我需要的范圍內的每個值:0-64,精度為0.001。
由於這個想法是用它來存儲,這實際上是更好,因為它允許從和轉換double
沒有任何分辨率損失。 它也更快。 實際上,它以具有更好的最小步長為名而失去了一些分辨率(小於16位),因此它可以表示任何輸入值而無需近似值-因此在這種情況下,LESS更重要。 對浮動分量使用完整的2 ^ 10分辨率將導致無法正確表示十進制值的奇數步。
class Half {
public:
Half() {}
Half(const double d) { load(d); }
operator double() const { return _d.i + ((double)_d.f / 1000); }
private:
struct Data {
unsigned short i : 6;
unsigned short f : 10;
};
void load(const double d) {
int i = d;
_d.i = i;
_d.f = round((d - i) * 1000);
}
Data _d;
};
最后解決方案有誤...對不起...
嘗試將指數更改為signed...。
問題在於,當指數變成負數時,當值<0.5時,會將指數另存為正數,這是當abs(val)<0.5時導致數字變大的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.