使用C或C++从整数创建浮点数的最快方法是什么?例如,我想从12345创建浮点数0.12345f。对我来说,一个慢的方法是从整数创建一个字符串,然后传递给atof。但是,一定有更快的方法来解决它,通过移位?
8aqjt8rx1#
你可以使用一个循环:
int ival = 12345;float fval = ival;while (fabs(fval) >= 1) fval /= 10;
int ival = 12345;
float fval = ival;
while (fabs(fval) >= 1) fval /= 10;
字符串一般来说,只有当你确定性能是一个真实的问题时,你才应该担心它,除非你需要每秒做数百万次,否则应该足够了。
ahy6op9u2#
实际上你要做的运算是x/10^d,其中x是你的数字,d是x中的位数。这使得它更容易一些。你所要做的就是数数。数数的方法有很多种。最简单的方法是
double y = 1;while (y <= x) y *= 10;return (double)x / y;
double y = 1;
while (y <= x)
y *= 10;
return (double)x / y;
字符串但如果你想快点...如果你的数字是32位整数,你可以使用这个技巧从位旋转黑客
unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of int r; // result goes hereint t; // temporarystatic unsigned int const PowersOf10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};t = (IntegerLogBase2(v) + 1) * 1233 >> 12; // (use a lg2 method from above)r = t - (v < PowersOf10[t]);
unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of
int r; // result goes here
int t; // temporary
static unsigned int const PowersOf10[] =
{1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000};
t = (IntegerLogBase2(v) + 1) * 1233 >> 12; // (use a lg2 method from above)
r = t - (v < PowersOf10[t]);
型当他们说“使用上面的lg 2方法”时,你可以使用他们在页面前面写的算法,比如
static const char LogTable256[256] = {#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)};unsigned int v; // 32-bit word to find the log ofunsigned r; // r will be lg(v)register unsigned int t, tt; // temporariesif (tt = v >> 16){ r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];}else { r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];}
static const char LogTable256[256] =
{
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
unsigned int v; // 32-bit word to find the log of
unsigned r; // r will be lg(v)
register unsigned int t, tt; // temporaries
if (tt = v >> 16)
r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
}
else
r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
型当然,这可能有些矫枉过正,但这恰恰说明了有多少种快速的方法可以做到这一点!
km0tfn4u3#
这将比“除以10直到数字缩放”的解决方案快一点,因为乘法比除法快。但我使用它的主要原因是因为它更准确:除以10会在每次除法时丢失精度,而乘以10则不会(直到你做23次,这比你需要处理一个长整数要多得多)。所以这里只有最后一个除法是不精确的:
double to_fraction(long mantissa) { double mag = fabs(mantissa), e = 10.; while (e < mag) e *= 10.; return mantissa / e;}
double to_fraction(long mantissa) {
double mag = fabs(mantissa), e = 10.;
while (e < mag) e *= 10.;
return mantissa / e;
字符串
zd287kbt4#
最快的方法是使用math.h中的log10()和pow()函数。
math.h
log10()
pow()
#include <math.h>// An integer representation of a fractional value less than 1.long integer_mantissa = 12345;// Use `log10()` to count the decimal digits in the number, minus 1.// Add back the 1 to get the total number of digits.long decimal_places = ((long)log10(integer_mantissa) + 1);// Get the scale factor used to shift the decimal point to the right// by raising 10 to the negative `decimal_places` power.double mantissa_scale = pow(10, -decimal_places);// Multiply the integer by our scale factor to get the final value.double fraction = integer_mantissa * mantissa_scale;
#include <math.h>
// An integer representation of a fractional value less than 1.
long integer_mantissa = 12345;
// Use `log10()` to count the decimal digits in the number, minus 1.
// Add back the 1 to get the total number of digits.
long decimal_places = ((long)log10(integer_mantissa) + 1);
// Get the scale factor used to shift the decimal point to the right
// by raising 10 to the negative `decimal_places` power.
double mantissa_scale = pow(10, -decimal_places);
// Multiply the integer by our scale factor to get the final value.
double fraction = integer_mantissa * mantissa_scale;
字符串此方法不包含任何循环或分支指令,使其成为任何具有本机浮点操作的架构上最快的实现。无论底层浮点表示如何,这也都可以工作,使其完全可移植到任何编译器或平台。
4条答案
按热度按时间8aqjt8rx1#
你可以使用一个循环:
字符串
一般来说,只有当你确定性能是一个真实的问题时,你才应该担心它,除非你需要每秒做数百万次,否则应该足够了。
ahy6op9u2#
实际上你要做的运算是x/10^d,其中x是你的数字,d是x中的位数。这使得它更容易一些。你所要做的就是数数。
数数的方法有很多种。最简单的方法是
字符串
但如果你想快点...
如果你的数字是32位整数,你可以使用这个技巧从位旋转黑客
型
当他们说“使用上面的lg 2方法”时,你可以使用他们在页面前面写的算法,比如
型
当然,这可能有些矫枉过正,但这恰恰说明了有多少种快速的方法可以做到这一点!
km0tfn4u3#
这将比“除以10直到数字缩放”的解决方案快一点,因为乘法比除法快。但我使用它的主要原因是因为它更准确:除以10会在每次除法时丢失精度,而乘以10则不会(直到你做23次,这比你需要处理一个长整数要多得多)。所以这里只有最后一个除法是不精确的:
字符串
zd287kbt4#
最快的方法是使用
math.h
中的log10()
和pow()
函数。字符串
此方法不包含任何循环或分支指令,使其成为任何具有本机浮点操作的架构上最快的实现。无论底层浮点表示如何,这也都可以工作,使其完全可移植到任何编译器或平台。