我希望能夠讓用戶給出double並以DEC 64 dpfp格式(http://www.wsmr.army.mil/RCCsite/Documents/106%20Previous%20Versions/106-07/appendixO.pdf)寫出。無法正確排列這些信息,任何人都有經驗或已經爲DEC類型編寫了轉換函數?將C++ double轉換爲DEC double
0
A
回答
0
這看起來很直截了當,讓我試試吧。請注意,我沒有任何方法來測試它是否正確。
std::vector<unsigned char> ToDEC64Float(double d)
{
uint64_t dec_bits = 0ULL;
if (d != 0.0)
{
assert(sizeof(double) == sizeof(uint64_t));
uint64_t bits = *reinterpret_cast<uint64_t*>(&d);
uint64_t fraction = bits & 0x000fffffffffffffULL;
int exp = (int)((bits >> 52) & 0x7ff) - 1023;
bool sign = (bool)(bits & 0x8000000000000000ULL);
// convert the individual values for the new format
fraction <<= 3;
exp += 1 + 128;
if (exp > 255)
throw std::overflow_error("overflow");
if (exp < 0 || (exp == 0 && fraction != 0))
throw std::underflow_error("underflow");
dec_bits = (uint64_t)sign << 63 | (uint64_t)exp << 55 | fraction;
}
std::vector<unsigned char> result;
for (int i = 0; i < 64; i+=8)
result.push_back((unsigned char)((dec_bits >> i) & 0xff));
return result;
}
0
double static const DECBytesToDouble(uint64_t value)
{
//DEC Byte Conversion Constants
static const float MANTISSA_CONSTANT = 0.5;
static const int32_t EXPONENT_BIAS = 128;
uint8_t * byte_array = (uint8_t*)&value;
uint8_t first = byte_array[0];
uint8_t second = byte_array[1];
uint8_t third = byte_array[2];
uint8_t fourth = byte_array[3];
uint8_t fifth = byte_array[4];
uint8_t sixth = byte_array[5];
uint8_t seventh = byte_array[6];
uint8_t eighth = byte_array[7];
// |second |first|fourth|third|sixth|fifth|eighth|seventh|
// |s|exponent|mantissa |
bool sign = second & 0x80;
std::cout<<"(DECBytesToDouble) Sign: "<<sign<<std::endl;
int32_t exponent = ((second & 0x7F) << 1) + ((first >> 7) & 0x1);
std::cout<<"(DECBytesToDouble) Exponent: "<<exponent<<std::endl;
int64_t mantissa = ((int64_t)(first & 0x7F) << 48) + ((int64_t)fourth << 40)
+ ((int64_t)third << 32) + ((int64_t)sixth << 24) + ((int64_t)fifth << 16)
+ ((int64_t)eighth << 8) + (int64_t) seventh;
std::cout<<"(DECBytesToDouble) Fraction: "<<mantissa<<std::endl;
double fraction = MANTISSA_CONSTANT;
for (int32_t i=0; i<55; i++)
{
fraction += ((mantissa >> i) & 0x1) * pow(2,i-56);
}//for
return pow(-1,sign)*fraction*pow(2,exponent-EXPONENT_BIAS);
}//DECBytesToDouble
uint64_t static const DoubleToDECBytes(double value)
{
static const int32_t EXPONENT_BIAS = 128;
uint64_t dec_bits = 0ULL;
if (value != 0.0)
{
uint64_t bits = *reinterpret_cast<uint64_t*>(&value);
uint64_t fraction = bits & 0x000fffffffffffffULL;
int exp = (int)((bits >> 52) & 0x7ff) - 1023;
bool sign = false;
if(value < 0)
{
sign = true;
}//if
std::cout<<"(DoubleToDECBytes) Sign: "<<sign<<std::endl;
// convert the individual values for the new format
fraction <<= 3;
exp += EXPONENT_BIAS + 1;
std::cout<<"(DoubleToDECBytes) Exponent: "<<exp<<std::endl;
std::cout<<"(DoubleToDECBytes) Fraction: "<<fraction<<std::endl;
if (exp > 255)
throw std::overflow_error("overflow");
if (exp < 0 || (exp == 0 && fraction != 0))
throw std::underflow_error("underflow");
dec_bits = (uint64_t)(sign << 63) | (uint64_t)(exp << 55) | fraction;
//|second |first|fourth|third|sixth|fifth|eighth|seventh|
uint8_t * byte_array = (uint8_t*)&dec_bits;
uint8_t first = byte_array[0];
uint8_t second = byte_array[1];
uint8_t third = byte_array[2];
uint8_t fourth = byte_array[3];
uint8_t fifth = byte_array[4];
uint8_t sixth = byte_array[5];
uint8_t seventh = byte_array[6];
uint8_t eighth = byte_array[7];
byte_array[7] = second;
byte_array[6] = first;
byte_array[5] = fourth;
byte_array[4] = third;
byte_array[3] = sixth;
byte_array[2] = fifth;
byte_array[1] = eighth;
byte_array[0] = seventh;
std::cout<<"(DoubleToDECBytes) Guess ="<<dec_bits<<std::endl;
}//if
/*std::vector<unsigned char> result;
for (int i = 0; i < 64; i+=8)
{
result.push_back((unsigned char)((dec_bits >> i) & 0xff));
}//for
uint64_t final_result = 0;
memcpy(&final_result, &result[0], sizeof(uint64_t));
std::cout<<"Final result: "<<final_result<<std::endl;*/
return dec_bits;
}//DoubleToDECBytes
Output:
input uint64_t value: 9707381994276473045
(DECBytesToDouble) Sign: 0
(DECBytesToDouble) Exponent: 145
(DECBytesToDouble) Fraction: 24184718387676855
output double value: 109527.7465
(DoubleToDECBytes) Sign: 0
(DoubleToDECBytes) Exponent: 145
(DoubleToDECBytes) Fraction: 24184718387676848
(DoubleToDECBytes) Guess =9705411669439479893
Converted double, uint64_t: 9705411669439479893
uint64_t difference: 1970324836993152
(DECBytesToDouble) Sign: 0
(DECBytesToDouble) Exponent: 0
(DECBytesToDouble) Fraction: 24184718387676848
output double value: 0.0000
+0
@MarkRansom以上是我目前所在的位置,無法完全轉換來回轉換 – favre45 2014-10-14 17:01:21
0
我才發現,libvaxdata C庫集成到我的C++的解決辦法是最好的一段路要走。在我的用例情況下,所需的只是一些字節翻轉,然而這些例程完美無缺地工作。
我在處理與IEEE/DEC類型的轉換時建議使用libvaxdata庫。
相關問題
- 1. C++將vector <pair <double,double >>轉換爲double *,double *?
- 2. 無法將double轉換爲double [] error
- 3. 如何將Double []轉換爲double []?
- 4. 無法將'double(_cdecl *)()'轉換爲'double'
- 5. 如何在Scala中將Array [(Double,Double)]轉換爲Array [Double]?
- 6. 將double轉換爲unsigned char?
- 7. 將double轉換爲float?
- 8. 將Double轉換爲DateTime?
- 9. 將「Double」轉換爲Int
- 10. 將int轉換爲double
- 11. 將double [] []轉換爲float [] []
- 12. mysql將float轉換爲double
- 13. .net將bytearray轉換爲double []
- 14. 將NSNumber轉換爲Double(CLLocationDegrees)
- 15. 將C#double轉換爲Pascal real
- 16. 在c#中將double [?]轉換爲object []#
- 17. 將Delphi Real48轉換爲C#double
- 18. C#:如何將TimeSpan值轉換爲double?
- 19. 將double轉換爲字符串C++?
- 20. Java錯誤:double無法轉換爲double []
- 21. 錯誤:無法從Double **轉換爲Double
- 22. 不能將'double'轉換爲'double(*)[5]'作爲參數'1'到'void one_set_avrg(double(*)[5])'
- 23. 無法將'double(*)[5]'轉換爲'double'作爲回報
- 24. 從int轉換爲double
- 25. 使用union將double轉換爲double使用
- 26. 如何將「格式化的double(String)」轉換爲double?
- 27. 如何將double *轉換爲數組<double>(6)
- 28. 錯誤C2440無法將void *轉換爲double **或double *
- 29. C++編譯器從double轉換爲int
- 30. Java「的」轉換爲double
刷新我的記憶,是DEC的大端還是小端? – 2014-10-10 15:42:39
Little-endian我相信 – favre45 2014-10-10 19:07:24
2分鐘後,我創建了自己的答案我發現這個:http://pubs.usgs.gov/of/2005/1424/of2005-1424_v1.2.pdf – 2014-10-10 21:01:36