C语言 如何创建一个尾数后有值的浮点数?

zlhcx6iw  于 2024-01-06  发布在  其他
关注(0)|答案(4)|浏览(150)

使用C或C++从整数创建浮点数的最快方法是什么?
例如,我想从12345创建浮点数0.12345f。
对我来说,一个慢的方法是从整数创建一个字符串,然后传递给atof。但是,一定有更快的方法来解决它,通过移位?

8aqjt8rx

8aqjt8rx1#

你可以使用一个循环:

  1. int ival = 12345;
  2. float fval = ival;
  3. while (fabs(fval) >= 1) fval /= 10;

字符串
一般来说,只有当你确定性能是一个真实的问题时,你才应该担心它,除非你需要每秒做数百万次,否则应该足够了。

ahy6op9u

ahy6op9u2#

实际上你要做的运算是x/10^d,其中x是你的数字,d是x中的位数。这使得它更容易一些。你所要做的就是数数。
数数的方法有很多种。最简单的方法是

  1. double y = 1;
  2. while (y <= x)
  3. y *= 10;
  4. return (double)x / y;

字符串
但如果你想快点...
如果你的数字是32位整数,你可以使用这个技巧从位旋转黑客

  1. unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of
  2. int r; // result goes here
  3. int t; // temporary
  4. static unsigned int const PowersOf10[] =
  5. {1, 10, 100, 1000, 10000, 100000,
  6. 1000000, 10000000, 100000000, 1000000000};
  7. t = (IntegerLogBase2(v) + 1) * 1233 >> 12; // (use a lg2 method from above)
  8. r = t - (v < PowersOf10[t]);


当他们说“使用上面的lg 2方法”时,你可以使用他们在页面前面写的算法,比如

  1. static const char LogTable256[256] =
  2. {
  3. #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
  4. -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
  5. LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
  6. LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
  7. };
  8. unsigned int v; // 32-bit word to find the log of
  9. unsigned r; // r will be lg(v)
  10. register unsigned int t, tt; // temporaries
  11. if (tt = v >> 16)
  12. {
  13. r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
  14. }
  15. else
  16. {
  17. r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
  18. }


当然,这可能有些矫枉过正,但这恰恰说明了有多少种快速的方法可以做到这一点!

展开查看全部
km0tfn4u

km0tfn4u3#

这将比“除以10直到数字缩放”的解决方案快一点,因为乘法比除法快。但我使用它的主要原因是因为它更准确:除以10会在每次除法时丢失精度,而乘以10则不会(直到你做23次,这比你需要处理一个长整数要多得多)。所以这里只有最后一个除法是不精确的:

  1. double to_fraction(long mantissa) {
  2. double mag = fabs(mantissa), e = 10.;
  3. while (e < mag) e *= 10.;
  4. return mantissa / e;
  5. }

字符串

zd287kbt

zd287kbt4#

最快的方法是使用math.h中的log10()pow()函数。

  1. #include <math.h>
  2. // An integer representation of a fractional value less than 1.
  3. long integer_mantissa = 12345;
  4. // Use `log10()` to count the decimal digits in the number, minus 1.
  5. // Add back the 1 to get the total number of digits.
  6. long decimal_places = ((long)log10(integer_mantissa) + 1);
  7. // Get the scale factor used to shift the decimal point to the right
  8. // by raising 10 to the negative `decimal_places` power.
  9. double mantissa_scale = pow(10, -decimal_places);
  10. // Multiply the integer by our scale factor to get the final value.
  11. double fraction = integer_mantissa * mantissa_scale;

字符串
此方法不包含任何循环或分支指令,使其成为任何具有本机浮点操作的架构上最快的实现。无论底层浮点表示如何,这也都可以工作,使其完全可移植到任何编译器或平台。

展开查看全部

相关问题