首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C/C++中的整数除法是否会遇到精度损失的问题?

C/C++中的整数除法是否会遇到精度损失的问题?
EN

Stack Overflow用户
提问于 2019-07-29 14:21:26
回答 3查看 2.2K关注 0票数 2

假设我们有三个整数(int、长、长、无符号int等)变量a, b, c。通常,表演

代码语言:javascript
运行
复制
c = a / b;

会导致分数的截断。但是,c是否有可能以不正确的值结束?

我不是说a/b可能超出了c's type.的范围,而是讨论了在C中如何实现整数除法。执行a / b首先生成浮点类型的中间结果,然后截断中间值吗?

如果是这样的话,我想知道中间值的精度损失是否会导致c值的不正确。例如,假设a/b的精确值为2,但中间结果是1.9999...,则c最终会得到一个不正确的值1。这种情况会发生吗?如果期望值在c类型的范围内,整数除法是否总是导致一个正确的值?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-07-29 14:32:04

执行a/b是否首先生成浮点类型的中间结果?

就语言而言,没有中间的结果。

如果期望值在c类型的范围内,整数除法总是得到正确的值吗?

是。

票数 6
EN

Stack Overflow用户

发布于 2019-07-29 14:28:48

C11标准第6.5.5节规定

当整数被除法时,/算子的结果是代数商,其中任意小数部分被丢弃。如果商数a/b 是可表示的,则表达式 (a/b)*b + a%b 应等于 a;

这意味着,在数学上,你不可能得到错误的结果。

票数 3
EN

Stack Overflow用户

发布于 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中设置错误的值。

考虑一下这个例子:

代码语言:javascript
运行
复制
#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

同样,如果您这样做:

代码语言:javascript
运行
复制
uint16_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);

32位int机的结果是-16.如果将a的类型更改为uint32_t,则数学发生在未签名的情况下:

代码语言:javascript
运行
复制
uint32_t a = 16;
int16_t b = -1;
int32_t result = a / b;
printf("%" PRId32 "\n", result);

其结果是of 在一台16位的机器上,你也可以从以前的0计算中得到。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57255807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档