我试图将一个双重分为整个和分数部分。我的代码工作正常,但由于我使用的微控制器在汇编中没有专用的乘法指令,所以它太慢了。例如,
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。还有其他方法吗?
答案 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);