Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.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++_Floating Point_Int_Precision - Fatal编程技术网

C++ 类型和结果之间的意外差异

C++ 类型和结果之间的意外差异,c++,floating-point,int,precision,C++,Floating Point,Int,Precision,为什么此代码返回不同的值?为什么Int type是错误的?尽管我无法重新生成gcc 4.9.2中的内容,但我在循环中添加了一些printf,如下所示: Int value: 950 Float value: 951 for(int i = number.length()-1; i >=0; i--) { valueInt += (number[i]-48) * std::lround(pow(10,i)); valueFloat += (number[i]-48) * p

为什么此代码返回不同的值?为什么Int type是错误的?

尽管我无法重新生成gcc 4.9.2中的内容,但我在循环中添加了一些printf,如下所示:

Int value: 950
Float value: 951
for(int i = number.length()-1; i >=0; i--)
{
    valueInt += (number[i]-48) * std::lround(pow(10,i));
    valueFloat += (number[i]-48) * pow(10,i);
}
得到:

printf("%d\n", pow(10, i));
printf("%f\n", pow(10, i));
我怀疑您看到这种行为是因为,它的签名最接近int:

浮动功率浮动基数、浮动指数


因此,pow返回一个浮点值,然后将其转换为int,这可能会导致某些精度的损失。

这是不一致的行为。在某些平台上,它甚至可以返回正确的整数。问题是在pow10中,这个函数返回一个浮点数,当将它添加到其他int或char时,它将返回另一个浮点数。然后将整数添加到int变量中,这意味着需要从float转换为int。浮点数可能是951或950.99999或类似的数字。如果将950.99999铸造为int,则为950。这就解释了结果

如果出于某种原因而希望使用int变量,而该变量似乎不存在,则应执行类似操作:

gsamaras@pythagoras:~$ g++ -Wall pc.cpp 
pc.cpp: In function ‘int main()’:
pc.cpp:14:27: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘__gnu_cxx::__promote_2<int, int, double, double>::__type {aka double}’ [-Wformat=]
  printf("%d\n", pow(10, i));
                           ^
gsamaras@pythagoras:~$ ./a.out 
1076101120
100.000000
1076101120
10.000000
1076101120
1.000000
Int value: 951
Float value: 951
问题是pow计算的值不是整数值,可能powx,y是explnx*y计算的-但它不一定是那样,而是作为浮点值,它会有一个小的舍入误差。这可能低于或高于正确的值,并且由于从浮点到int的转换是通过截断实现的,因此950.999996将转换为950,而不是951。在这种情况下,您可以通过将pow的结果四舍五入到最近的值而不是截断来解决这个问题[假设结果与无限精确值的偏差小于+/-0.5]

浮点值的计算方式始终具有一定的精度。整数计算总是精确到计算本身的最小整数值,而CouWSE中,C和C++的规则是,如果一方是浮点,则计算在浮点上执行。 我将从代码中完全消除经常麻烦的pow的使用。对于计算正确的值和速度,更好的方法是使用每次循环迭代更新的乘数值。大概是这样的:

Int value: 950
Float value: 951
for(int i = number.length()-1; i >=0; i--)
{
    valueInt += (number[i]-48) * std::lround(pow(10,i));
    valueFloat += (number[i]-48) * pow(10,i);
}
[我同时显示整数和浮点乘法器,这不是严格要求的,在第二个循环中使用imult可以得到同样好的答案-但无论哪种方式,它都会变成一个浮点值,所以我想我会同时显示这两个变量]


对于int的有效范围和float的有效范围,这将给出更准确的结果。当然,浮点格式的整数值在开始被切碎之前被限制为23位,因为浮点格式中缺少可用的精度。因此,任何超过830万的值都将丢失最低有效位。

因为pow计算浮点结果,转换为int时会被截断。下次如果你说为什么你会期望输出不同,我将向上投票,因为你在这里还是新手。为什么int type在那里是错误的?-它从来没有错过。这个程序完全按照你说的去做。如果结果不是你期望的,你没有告诉它你认为你做了什么。在编译器或标准库中查找错误的可能性很小,特别是对于初学者而言-或者使用round——但我只需要从1开始,每次乘以10,累积一个整数乘数——很可能比调用pow更快(即使对于浮点值也是如此)。round不是返回浮点吗?然而,另一种解决方案更好,但这种情况可能并不总是关于POWER,您可能想提及std::lround。是的,它更好。舍入返回四舍五入到最接近整数的浮点。因此,假设pow实际返回的值相当接近正确的值,它将给出一个正确的值作为整数结果[并且对于任何有效的整数和浮点值,一旦超出浮点范围,它可能会出错]。
int imult = 1;
float fmult = 1.0f;
for(int i = number.length()-1; i >=0; i--)
{
    valueInt += (number[i]-48) * imult;
    imult *= 10;
    valueFloat += (number[i]-48) * fmult;
    fmult *= 10.0f;
}