在我多年的嵌入式编程生涯中,我通常不需要使用负数。这很疯狂,但它们在我的工作中并不经常出现。
我目前正在处理一个传感器读数,该读数可以是正值,也可以是负值,需要按 0.006 缩放,保留符号。为了避免在运行时进行不必要的浮点计算,我有一个算法将其转换为分子和分母 (3/500)。对于正数,一切都按预期进行,但对于负数,情况如下:
Raw data: -103
Multiplied by 3: -309
Divided by 500: 36893488147419102
我弄清楚了这个数字的来源,并且我有一个解决方法,但我宁愿相信数学就是数学。
这是相同的十六进制计算:
Raw data: 0xFFFFFFFFFFFFFF99
Multiplied by 3: 0xFFFFFFFFFFFFFECB
Divided by 500: 0x0083126E978D4FDE
在计算器 (SpeedCrunch) 中:
0xFFFFFFFFFFFFFECB/500 = 0x83126E978D4FDE.9D2F1A9FBE76C8B44
原始 36893488147419102
是 SpeedCrunch 结果的组成部分 0x83126E978D4FDE
。
我不想保存符号,进行正除法,然后每次用负数除法时都重新添加符号。这是怎么回事?
环境是CortexM3 micro,使用c++11的GCC4.9.3。计算在 int64_t
上完成,分子/分母为 uint64_t
。
编辑: 以下是响应 Michael 评论的代码片段:
int64_t data = -103;
uint64_t resolutionNumerator = 3;
uint64_t resolutionDenominator = 500;
data *= resolutionNumerator;
data /= resolutionDenominator;
最佳答案
使用相同宽度的有符号和无符号整数(例如 uint64_t
和 int64_t
)进行运算,会导致有符号操作数转换为无符号操作数的类型。
因此这两个表达式是等价的:
(int64_t) -103 * (uint64_t) 3/(uint64_t) 500
(uint64_t) -103 * (uint64_t) 3/(uint64_t) 500
如果分子和分母使用有符号类型 int64_t
,则结果将保留符号。
关于带负数的嵌入式除法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34231301/