Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是否可以用保真度将浮点双精度整数往返到两个十进制整数?_C_Ieee 754 - Fatal编程技术网

C 是否可以用保真度将浮点双精度整数往返到两个十进制整数?

C 是否可以用保真度将浮点双精度整数往返到两个十进制整数?,c,ieee-754,C,Ieee 754,我试图辨别是否有可能将双精度IEEE浮点值分解为两个整数,并在以后以完全保真度重新组合它们。想象一下这样的情景: double foo = <inputValue>; double ipart = 0; double fpart = modf(foo, &ipart); int64_t intIPart = ipart; int64_t intFPart = fpart * <someConstant>; double bar = ((double)ipart

我试图辨别是否有可能将双精度IEEE浮点值分解为两个整数,并在以后以完全保真度重新组合它们。想象一下这样的情景:

double foo = <inputValue>;
double ipart = 0;
double fpart = modf(foo, &ipart);

int64_t intIPart = ipart;
int64_t intFPart = fpart * <someConstant>;

double bar = ((double)ipart) + ((double)intFPart) / <someConstant>;

assert(foo == bar);
double whole = // your original value
long iPart = (long)whole;
double fraction = whole - iPart;
long fPart = fraction * (2 << 63);
double foo=;
双ipart=0;
双fpart=modf(foo和ipart);
int64_t intIPart=ipart;
int64_t intFPart=fpart*;
双栏=((双)ipart)+((双)intFPart)/;
断言(foo==bar);
逻辑上很明显,任何64位的数量都可以存储为128位(即仅存储文字位)。这里的目标是将双精度的整数部分和小数部分分解为整数表示(与存储格式我不控制的API接口)当重新组合两个64位整数时,返回一个位精确的双精度

我对IEEE浮点有一个概念性的理解,我知道双精度是以2为基数存储的。根据经验,我观察到,使用上述方法,有时
foo!=即使是非常大的
值,也可以使用条形图。我已经离开学校有一段时间了,我无法完全理解在不同的基础(或其他因素)下这是否可能

编辑:

我猜这在我的大脑中是暗示/理解的,但在这里没有捕捉到:在这种情况下,我保证问题中的双精度的总体大小将始终在+/-2^63(和>2^-64)范围内。基于这种理解,整数部分保证适合64位整数类型,那么我的期望是,在16位十进制精度的情况下,小数部分也应该很容易在64位整数类型中表示

这里的目标是分解整数部分和小数部分 将双精度转换为整数表示

你甚至不能可靠地得到整数部分或小数部分。问题在于,您似乎误解了浮点数的存储方式。它们没有整数部分和小数部分。它们有一个有效数字部分,称为尾数和一个指数。指数本质上是向上或向下缩放尾数,类似于科学记数法的工作原理

双精度浮点数的指数有11位,给出的值范围类似于2-1022…21023。如果要存储整数和小数部分,则需要两个整数,每个整数大约有210位。不过,这是一种愚蠢的做法,因为只有尾数中的位才是有意义的,所以这些位中的大部分都会被闲置。使用两个很长的整数可以让您以相同的精度表示整个double范围内的所有值,这是double无法做到的。例如,你可以有一个非常大的整数部分和一个非常小的小数部分,但这个数字不能用双精度来表示

更新

如您在评论中所述,如果您知道所讨论的值在±263范围内,您可以使用以下答案:

double foo = <inputValue>;
double ipart = 0;
double fpart = modf(foo, &ipart);

int64_t intIPart = ipart;
int64_t intFPart = fpart * <someConstant>;

double bar = ((double)ipart) + ((double)intFPart) / <someConstant>;

assert(foo == bar);
double whole = // your original value
long iPart = (long)whole;
double fraction = whole - iPart;
long fPart = fraction * (2 << 63);
double整数=//原始值
长iPart=(长)整个;
双分数=整数-iPart;
长fPart=分数*(2
这里的目标是分解整数部分和小数部分
将双精度转换为整数表示

你甚至不能可靠地得到整数部分或小数部分。问题是你似乎误解了浮点数的存储方式。它们没有整数部分和小数部分。它们有一个有效数字部分,称为尾数和指数。指数本质上是将尾数向上或向上缩放自己的,类似于科学记数法的工作原理

双精度浮点数的指数有11位,给出的值范围类似于2-1022…21023。如果要存储整数和小数部分,则需要两个整数,每个整数约有210位。不过,这是一种愚蠢的方法——这些位中的大多数都将不使用,因为只有尾数中的位是有意义的。使用两个很长的整数可以让你以相同的精度表示整个double范围内的所有值,这是double无法做到的。例如,你可以有一个很大的整数部分和一个很小的小数部分,但这个数字是double不能准确地表示

更新

如您在评论中所述,如果您知道所讨论的值在±263范围内,您可以使用以下答案:

double foo = <inputValue>;
double ipart = 0;
double fpart = modf(foo, &ipart);

int64_t intIPart = ipart;
int64_t intFPart = fpart * <someConstant>;

double bar = ((double)ipart) + ((double)intFPart) / <someConstant>;

assert(foo == bar);
double whole = // your original value
long iPart = (long)whole;
double fraction = whole - iPart;
long fPart = fraction * (2 << 63);
double整数=//原始值
长iPart=(长)整个;
双分数=整数-iPart;

long fPart=fraction*(2有关双精度的格式,请参见维基百科:

IEEE双格式编码三个整数:有效位、指数和符号位。 以下代码将以IEEE双精度格式提取三个组成整数:

double d = 2.0;  

// sign bit
bool s = (*reinterpret_cast<int64_t*>(&d)) >> 63;

// significand
int64_t m = *reinterpret_cast<int64_t*>(&d) & 0x000FFFFFFFFFFFFFULL;

// exponent
int64_t e = ((*reinterpret_cast<int64_t*>(&d) >> 52) & 0x00000000000007FFULL) - 1023;

// now the double d is exactly equal to s * (1 + (m / 2^52)) * 2^e
// print out the exact arithmatic expression for d:

std::cout << "d = " << std::dec << (s ? "-(1 + " : "(1 + (") << m << "/" << (1ULL << 52) << ")) x 2^" << e;
double d=2.0;
//符号位
布尔s=(*重新解释演员阵容(&d))>>63;
//意义
int64_t m=*重新解释强制转换(&d)&0x000fffffffffull;
//指数
int64_t e=(*重新解释(&d)>>52)和0x00000000000007FFULL)-1023;
//现在双d正好等于s*(1+(m/2^52))*2^e
//打印出d的精确算术表达式:

std::cout有关双精度的格式,请参见维基百科:

IEEE双格式编码三个整数:有效位、指数和符号位。 以下代码将以IEEE双精度格式提取三个组成整数:

double d = 2.0;  

// sign bit
bool s = (*reinterpret_cast<int64_t*>(&d)) >> 63;

// significand
int64_t m = *reinterpret_cast<int64_t*>(&d) & 0x000FFFFFFFFFFFFFULL;

// exponent
int64_t e = ((*reinterpret_cast<int64_t*>(&d) >> 52) & 0x00000000000007FFULL) - 1023;

// now the double d is exactly equal to s * (1 + (m / 2^52)) * 2^e
// print out the exact arithmatic expression for d:

std::cout << "d = " << std::dec << (s ? "-(1 + " : "(1 + (") << m << "/" << (1ULL << 52) << ")) x 2^" << e;
double d=2.0;
//符号位
布尔s=(*重新解释演员阵容(&d))>>63;
//意义
int64_t m=*重新解释强制转换(&d)&0x000fffffffffull;
//指数
int64_t e=(*重新解释(&d)>>52)和0x00000000000007FFULL)-1023;
//现在是双d i