c - 无符号整数运算结果错误

标签 c unsigned-integer

我对无符号整数变量的算术运算有疑问。

所有变量都定义为 uint32_t。 这是算术运算:

batt += (uint32_t) ((((charg - discharg) * (time_now - time_old)) / 1000) + 0.5);

操作前的值为:

batt = 8999824
charg = 21
discharg = 1500
time_now = 181
time_old = 132

问题是运行后的结果是

batt = 13294718

代替

batt = 8999752

这是什么原因?

提前致谢。

最佳答案

你有两个问题。

  1. charg < discharg因此为 charg - discharg 创建了 4294965817 的环绕答案.请参阅下文,了解您最终得到 13294718 的原因。

  2. /1000 之前执行偏置 (+ 0.5) , 不然整数除法都准备好把小数部分都扔了。

建议修复 1:确保充电 >= 放电。

建议修复 1:将 charg、discharg、time_now、time_old 和 batt 更改为 int32_t .

建议的修复 2:将舍入更改为 batt += (uint32_t) ((Product / 1000.0) + 0.5);

建议的修复 2:将舍入更改为 batt += (Product + 500*sign(Product))/1000;


明显的错误代码 - 一步一步。

uint32_t batt = 8999824;
uint32_t charg = 21;
uint32_t discharg = 1500;
uint32_t time_now = 181;
uint32_t time_old = 132;
// batt += (uint32_t) ((((charg - discharg) * (time_now - time_old)) / 1000) + 0.5);

// The big problem occurs right away.
// Since charg is less than discharg, and unsigned arithmetic "wrap around", 
// you get (21 - 1500) + 2**32 = (21 - 1500) + 4294967296 = 4294965817
uint32_t d1 = charg - discharg;
uint32_t d2 = time_now - time_old; // 49
// The product of d1 and d2 will overflow and the result is mod 4294967296
// (49 * 4294965817) = 210453325033
// 210453325033 mod 4294967296 = 4294894825
uint32_t p1 = d1 * d2;
uint32_t q1 = p1/1000;  // 4294894825/1000 = 4294894.825.  round to 0 --> 4294894
double s1 = q1 + 0.5;  //  4294894 + 0.5 --> 4294894.5;
uint32_t u1 = (uint32_t) s1; // 4294894.5 round to 0 --> 4294894
batt += u1; // 8999824 + 4294894 --> 13294718

关于c - 无符号整数运算结果错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16142217/

相关文章:

c++ - `-fno-semantic-interposition` 与 `-fvisibility=protected` 究竟有何不同?

c - 多线程:简单程序段错误(核心转储)

将 Long 转换为 Unsigned Short Int/Strtol

c - 架构无关代码

c - 特定线程数的 OpenMP 急剧减速

c - C 中的二叉搜索树,段错误

c - 按名称排序结构(双向链表)

c++ - 如何在不改变顺序的情况下将 int64 值转移到无符号 int64 空间?

iphone - 如何将 unsigned int 转换为 NSString?

将无符号字符转换为有符号整数