假设我们有三个整数(int、长、长、无符号int等)变量a, b, c。通常,表演
c = a / b;会导致分数的截断。但是,c是否有可能以不正确的值结束?
我不是说a/b可能超出了c's type.的范围,而是讨论了在C中如何实现整数除法。执行a / b首先生成浮点类型的中间结果,然后截断中间值吗?
如果是这样的话,我想知道中间值的精度损失是否会导致c值的不正确。例如,假设a/b的精确值为2,但中间结果是1.9999...,则c最终会得到一个不正确的值1。这种情况会发生吗?如果期望值在c类型的范围内,整数除法是否总是导致一个正确的值?
发布于 2019-07-29 14:32:04
执行a/b是否首先生成浮点类型的中间结果?
就语言而言,没有中间的结果。
如果期望值在c类型的范围内,整数除法总是得到正确的值吗?
是。
发布于 2019-07-29 14:28:48
C11标准第6.5.5节规定
当整数被除法时,
/算子的结果是代数商,其中任意小数部分被丢弃。如果商数a/b是可表示的,则表达式(a/b)*b + a%b应等于a;。
这意味着,在数学上,你不可能得到错误的结果。
发布于 2019-07-29 15:45:10
假设我们有三个整数(int,长,无符号int,等等)变量a,b,c。 C=a/ b; 会导致分数的截断。但是,
c是否有可能以不正确的值结束?我不是说a/b可能超出c型的范围。
例如,如果不遵守所有规则,就不可能出现最后一个数字的除法错误。C11 6.5.5p6
当整数被除法时,
/算子的结果是任何小数部分被丢弃的代数商。
也就是说,结果不是“接近”的,而是与a/b完全相同的,在代数上,只是在被丢弃的点之后的任何东西。
这并不意味着不会有任何问题:在数学上,a / b的除法可能不是超出c类型的范围,而是超出了除法本身使用的类型的范围,这可能导致在c中设置错误的值。
考虑一下这个例子:
#include <stdio.h>
#include <inttypes.h>
int main(void) {
int32_t a = INT32_MIN;
int32_t b = -1;
int64_t c = a / b;
printf("%" PRId64, c);
}INT32_MIN / -1的划分结果在c中具有代表性,即INT32_MAX + 1,即阳性。然而,在32位平台上,算法发生在32位上,这种分割会产生一个整数溢出,导致行为未定义。在我的计算机上发生的事情是,如果我在没有优化的情况下编译,就会中止程序。如果我在编译时启用了优化(-O3),编译器将在编译时解析此计算,并以一种特殊的方式处理溢出,并生成结果为负值的-2147483648。
同样,如果您这样做:
uint16_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);32位int机的结果是-16.如果将a的类型更改为uint32_t,则数学发生在未签名的情况下:
uint32_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);其结果是of 在一台16位的机器上,你也可以从以前的0计算中得到。
https://stackoverflow.com/questions/57255807
复制相似问题