简体   繁体   中英

int32_t to int64_t (or to float)

I have a very simple algorithm written in C, which takes values from array of int16_t , multiplies those values by their positions and stores into array of int32_t . There is another variable sum of type int64_t storing sum of all values in the resulting _slops array. Here is the code.

#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);

When I run the code, I see that resulting array of _slops has correct values in it, but the sum variable has same value all the time.

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

I tried to change type of sum to float , but the result stayed the same. I am quite sure I do something wrong with type casting ( int32_t to int64_t or int32_t to float ), but I wasn't able to find the right way for doing it.

What is the right way for doing this in C? And in general, if I multiply two int16_t values, and what to have a larger result (let's say int32_t ), how do I do this? Any help is highly appreciated.

Unless int64_t is an alias for int on your machine, you are using the wrong printf format directive. Try this instead:

LOGD("sum: %" PRId64, sum);

PRId64 is a macro defined in <inttypes.h> .

If you are using GCC, compiling with -Wformat would have generated an error about a format mismatch. -Wall will include -Wformat , along with many other useful warnings.

To your second question (about how to widen a result of a binary arithmetic operation that uses narrow type arguments), this is done by making at least one of the operands the width you desire. This can be done with a cast:

int16_t a = A_VAL;
int16_t b = B_VAL;
int32_t c = a + (int32_t)b;

As indicated by maverik 's answer , you have a possibility for signed integer overflow in the expression that is assigned to _slops[pos] . If _overlapSize is greater than 2 9 , then the largest product of pos * (_overlapSize - pos) is greater than 2 16 , meaning its product against from[pos] could have a result greater than 2 31 .

Here is the problem:

_slops[pos] = (from[pos] * pos * (_overlapSize - pos));

The _slops[pos] is a type of int32_t . The expression (from[pos] * pos * (_overlapSize - pos)) in some cases cannot be stored in int32_t because from[pos] is int16_t is multiplied by pos which is int32_t and the result can be bigger than int32_t (consider maximum value for int16_t that is 2^15 and maximum value for int32_t that is 2^31 . 2^15 * 2^31 = 2^46 which can't be stored as int32_t without truncating.

But you write it back to _slops[pos] which is int32_t . In this line:

sum += (int64_t) _slops[pos];

cast is useless and doesn't prevent narrowing. I suggest change _slops type to int64_t * or to use temporary variable to calculate the result:

int64_t tmp = ((int64_t) from[pos] * pos * (_overlapSize - pos));

I don't know how big can the pos be but the overall expression is not safe in this sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM