我有一个用C编写的非常简单的算法,它从int16_t
数组中获取值,将这些值乘以它们的位置并存储到int32_t
的数组中。还有另一个类型sum
的变量int64_t
,它存储了生成的_slops
数组中所有值的总和。这是代码。
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
// these variables initialized separately
int16_t *from;
int32_t *_slops;
int32_t _overlapSize;
...
// main algorithm
int32_t pos;
int64_t sum = 0;
for(pos = 0; pos < _overlapSize; pos++) {
_slops[pos] = (from[pos] * pos * (_overlapSize - pos));
sum += (int64_t) _slops[pos];
if (pos == 2) {
LOGD("1 ---: %d", (from[pos] * pos * (_overlapSize - pos)));
LOGD("2 ---: %d", _slops[pos]);
LOGD("3 sum: %d", sum);
}
}
LOGD("sum: %d", sum);
当我运行代码时,我发现_slops
生成的数组中包含正确的值,但sum
变量始终具有相同的值。
02-26 15:58:10.762: D/player(17466): 1 ---: 1154560
02-26 15:58:10.762: D/player(17466): 2 ---: 1154560
02-26 15:58:10.762: D/player(17466): 3 sum: 1504780888
02-26 15:58:10.762: D/player(17466): sum: 1504780904
02-26 15:58:10.840: D/player(17466): 1 ---: 890560
02-26 15:58:10.840: D/player(17466): 2 ---: 890560
02-26 15:58:10.848: D/player(17466): 3 sum: 1504780888
02-26 15:58:10.848: D/player(17466): sum: 1504780904
02-26 15:58:10.848: D/player(17466): 1 ---: 1791680
02-26 15:58:10.848: D/player(17466): 2 ---: 1791680
02-26 15:58:10.848: D/player(17466): 3 sum: 1504780888
02-26 15:58:10.848: D/player(17466): sum: 1504780904
我尝试将sum
的类型更改为float
,但结果保持不变。我很确定我在输入类型时遇到了问题(int32_t
到int64_t
或int32_t
到float
),但我无法找到正确的方法它
在C中执行此操作的正确方法是什么?一般来说,如果我乘以两个int16_t
值,以及得到更大结果的内容(假设int32_t
),我该怎么做?任何帮助都非常感谢。
答案 0 :(得分:4)
除非int64_t
是您计算机上int
的别名,否则您使用的是错误的printf
格式指令。试试这个:
LOGD("sum: %" PRId64, sum);
PRId64
是<inttypes.h>
中定义的宏。
如果您正在使用GCC,则使用-Wformat
进行编译会产生有关格式不匹配的错误。 -Wall
将包含-Wformat
以及许多其他有用的警告。
关于你的第二个问题(关于如何扩展使用窄类型参数的二进制算术运算的结果),这可以通过使至少一个操作数达到你想要的宽度来完成。这可以通过演员表来完成:
int16_t a = A_VAL;
int16_t b = B_VAL;
int32_t c = a + (int32_t)b;
如maverik的answer所示,您可能会在分配给_slops[pos]
的表达式中出现有符号整数溢出。如果_overlapSize
大于2 9 ,那么pos * (_overlapSize - pos)
的最大乘积大于2 16 ,这意味着它的乘积对{{1}可能有大于2 31 的结果。
答案 1 :(得分:3)
问题在于:
_slops[pos] = (from[pos] * pos * (_overlapSize - pos));
_slops[pos]
是一种int32_t
。在某些情况下,(from[pos] * pos * (_overlapSize - pos))
表达式无法存储在int32_t
中,因为from[pos]
int16_t
乘以pos
int32_t
,结果可以大于int32_t
(考虑int16_t
的最大值为2^15
,int32_t
的最大值为2^31
。2^15
* {{ 1}} = 2^31
,如果不截断,则无法存储为2^46
。
但是你把它写回int32_t
_slops[pos]
。在这一行:
int32_t
演员没用,也不能阻止缩小。我建议将sum += (int64_t) _slops[pos];
类型更改为_slops
或使用临时变量来计算结果:
int64_t *
我不知道int64_t tmp = ((int64_t) from[pos] * pos * (_overlapSize - pos));
有多大,但从这个意义上说整体表达并不安全。