4

我试图将一个 double 分成它的整体和分数部分。我的代码可以工作,但是考虑到我使用的微控制器在汇编中没有专用的乘法指令,它太慢了。例如,

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。还有其他方法吗?

4

2 回答 2

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 数字,你最好只提取尾数,甚至手动完成整个操作。

于 2013-07-05T15:54:32.993 回答
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);
于 2013-07-05T16:07:42.917 回答