将数字拆分为整数和小数部分的最有效方法

时间:2013-07-05 15:22:52

标签: c optimization

我试图将一个双重分为整个和分数部分。我的代码工作正常,但由于我使用的微控制器在汇编中没有专用的乘法指令,所以它太慢了。例如,

temp = ((int)(tacc - temp); // This line takes about 500us

但是,如果我这样做,

temp = (int)(100*(tacc-temp)); // This takes about 4ms

我可以加速微控制器,但由于我试图保持低功耗,我很好奇是否有可能更快地做到这一点。这是我真正对优化感兴趣的小部分:

    txBuffer[5] = ((int)tacc_y); // Whole part
    txBuffer[6] = (int)(100*(tacc_y-txBuffer[5])); // 2 digits of fraction

我记得有一种快速的方法是使用轮班乘以10,这样:

a * 10 = (a << 2 + a) << 1

我可能会嵌套这个并乘以100。还有其他方法吗?

2 个答案:

答案 0 :(得分:2)

我相信正确的答案,可能不是最快的,是:

double whole = trunc(tacc_y);
double fract = tacc_y - whole;

// first, extract (some of) the data into an int
fract = fract * (1<<11);         // should be just an exponent change
int ifract = (int)trunc(fract);

// next, decimalize it (I think)
ifract = ifract * 1000;          // Assuming integer multiply available
ifract = ifract >> 11;

txBuffer[5] = (int)whole;
txBuffer[6] = ifract

如果整数乘法不正确,那么你的移位技巧现在应该有用了。

如果浮点乘法太愚蠢而不能快速编辑指数,那么你可以手动地通过钻头来进行,但我不建议将它作为第一个选项。在任何情况下,一旦你得到了比特笨拙的FP数字,你也可以只提取尾数,甚至手动完成整个操作。

答案 1 :(得分:1)

我假设您正在使用双打。您可以尝试按位double分开:

double input = 10.64;

int sign = *(int64_t *)&input >> 63;

int exponent = (*(int64_t *)&input >> 52) & 0x7FF;

int64_t fraction = (*(int64_t *)&input) & 0xFFFFFFFFFFFFF;
fraction |= 0x10000000000000;

int64_t whole = fraction >> (52 + 1023 - exponent);

int64_t digits = ((fraction - (whole << (52 + 1023 - exponent))) * 100) >> (52 + 1023 - exponent);

printf("%lf, %ld.%ld\n", input, whole, digits);