获得10的幂的最快方法
Fastest way to obtain a power of 10
我将在此处使用 Java 作为示例,因为它可能完全是特定于语言的,但我通常对执行此操作的方法很感兴趣。
当然,最简单明了的方法是这样的:
Math.pow(10, x)
但据我所知,电源是一项相当昂贵的操作。因此我认为应该有更好的方法,因为它看起来很明显 - 我只需要在 1!
之后有 x 个零
编辑:
是的,这可能是过早的优化。上下文是四舍五入到小数点后n位,常用的是这样的:
private final static int[] powersOf10 = {1, 10, 100, 1000, 10000};
public static double round(double number, int decimals) {
if(decimals < 5)
return Math.rint(number / powersOf10[decimals]) * powersOf10[decimals];
double c = Math.pow(10, decimals);
return Math.rint(number * c) / c;
}
这是我当前使用的舍入函数,如您所见,我已经对最常用的值使用了查找 table,但我仍然很好奇是否有一些位魔术或类似的东西改进这个。
最快的方法是
static final int[] POWERS_OF_10 = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
static int powerOfTen(int pow) {
return POWERS_OF_10[pow];
}
...因为没有更高的 10 次方符合 int
。对不起,如果你期待更酷的东西。
这是我的解决方案:
double number = 7893.147895673;
int dp = 7;
String pattern = ".";
for (int i = 1; i <= dp; i++) {
pattern += "#";
}//for (int i = 1; i <= dp; i++)
DecimalFormat df = new DecimalFormat (pattern);
System.out.println(df.format(number));
对此我很满意,我三天前开始学习 Java,我很喜欢!
这个问题很老了,但对于通过搜索登陆这里的人来说,我希望这有用。
我使用 JMH 测试了三种方法的性能:
Math.pow(10, exponent)
- 根据已接受的答案在数组中查找
- 在硬编码的
switch
语句中查找。
这是 JMH 基准代码:
private static final long[] POWERS_OF_TEN = {
10L,
100L,
1_000L,
10_000L,
100_000L,
1_000_000L,
10_000_000L,
100_000_000L,
1_000_000_000L,
10_000_000_000L,
100_000_000_000L,
1_000_000_000_000L,
10_000_000_000_000L,
100_000_000_000_000L,
1_000_000_000_000_000L};
int exponent;
@Setup(Level.Iteration) public void randomExponent()
{
exponent = RAND.nextInt(16);
}
@Benchmark public long mathPow()
{
return (long) Math.pow(10, exponent);
}
@Benchmark public long arrayLookup()
{
return POWERS_OF_TEN[exponent];
}
@Benchmark public long switchLookup()
{
switch (exponent)
{
case 1: { return 10L; }
case 2: { return 100L; }
case 3: { return 1_000L; }
case 4: { return 10_000L; }
case 5: { return 100_000L; }
case 6: { return 1_000_000L; }
case 7: { return 10_000_000L; }
case 8: { return 100_000_000L; }
case 9: { return 1_000_000_000L; }
case 10: { return 10_000_000_000L; }
case 11: { return 100_000_000_000L; }
case 12: { return 1_000_000_000_000L; }
case 13: { return 10_000_000_000_000L; }
case 14: { return 100_000_000_000_000L; }
case 15: { return 1_000_000_000_000_000L; }
}
return 0L;
}
并且(鼓声......)这是结果:
Benchmark Mode Cnt Score Error Units
PowerOfTenBenchmark.mathPow thrpt 15 24.134 ± 32.132 ops/us
PowerOfTenBenchmark.arrayLookup thrpt 15 515.684 ± 10.056 ops/us
PowerOfTenBenchmark.switchLookup thrpt 15 461.318 ± 4.941 ops/us
所以#2 数组查找是最快的,确认接受的答案是正确的。
如果您认为 POWERS_OF_TEN
数组字面值初始化器很丑陋(我同意),还有一种更短且可能更不容易出错的方法:
private static final long[] POWERS_OF_TEN = IntStream.range(0, 16)
.mapToLong(i -> (long) Math.pow(10, i)).toArray();
我将在此处使用 Java 作为示例,因为它可能完全是特定于语言的,但我通常对执行此操作的方法很感兴趣。
当然,最简单明了的方法是这样的:
Math.pow(10, x)
但据我所知,电源是一项相当昂贵的操作。因此我认为应该有更好的方法,因为它看起来很明显 - 我只需要在 1!
之后有 x 个零编辑: 是的,这可能是过早的优化。上下文是四舍五入到小数点后n位,常用的是这样的:
private final static int[] powersOf10 = {1, 10, 100, 1000, 10000};
public static double round(double number, int decimals) {
if(decimals < 5)
return Math.rint(number / powersOf10[decimals]) * powersOf10[decimals];
double c = Math.pow(10, decimals);
return Math.rint(number * c) / c;
}
这是我当前使用的舍入函数,如您所见,我已经对最常用的值使用了查找 table,但我仍然很好奇是否有一些位魔术或类似的东西改进这个。
最快的方法是
static final int[] POWERS_OF_10 = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
static int powerOfTen(int pow) {
return POWERS_OF_10[pow];
}
...因为没有更高的 10 次方符合 int
。对不起,如果你期待更酷的东西。
这是我的解决方案:
double number = 7893.147895673;
int dp = 7;
String pattern = ".";
for (int i = 1; i <= dp; i++) {
pattern += "#";
}//for (int i = 1; i <= dp; i++)
DecimalFormat df = new DecimalFormat (pattern);
System.out.println(df.format(number));
对此我很满意,我三天前开始学习 Java,我很喜欢!
这个问题很老了,但对于通过搜索登陆这里的人来说,我希望这有用。
我使用 JMH 测试了三种方法的性能:
Math.pow(10, exponent)
- 根据已接受的答案在数组中查找
- 在硬编码的
switch
语句中查找。
这是 JMH 基准代码:
private static final long[] POWERS_OF_TEN = {
10L,
100L,
1_000L,
10_000L,
100_000L,
1_000_000L,
10_000_000L,
100_000_000L,
1_000_000_000L,
10_000_000_000L,
100_000_000_000L,
1_000_000_000_000L,
10_000_000_000_000L,
100_000_000_000_000L,
1_000_000_000_000_000L};
int exponent;
@Setup(Level.Iteration) public void randomExponent()
{
exponent = RAND.nextInt(16);
}
@Benchmark public long mathPow()
{
return (long) Math.pow(10, exponent);
}
@Benchmark public long arrayLookup()
{
return POWERS_OF_TEN[exponent];
}
@Benchmark public long switchLookup()
{
switch (exponent)
{
case 1: { return 10L; }
case 2: { return 100L; }
case 3: { return 1_000L; }
case 4: { return 10_000L; }
case 5: { return 100_000L; }
case 6: { return 1_000_000L; }
case 7: { return 10_000_000L; }
case 8: { return 100_000_000L; }
case 9: { return 1_000_000_000L; }
case 10: { return 10_000_000_000L; }
case 11: { return 100_000_000_000L; }
case 12: { return 1_000_000_000_000L; }
case 13: { return 10_000_000_000_000L; }
case 14: { return 100_000_000_000_000L; }
case 15: { return 1_000_000_000_000_000L; }
}
return 0L;
}
并且(鼓声......)这是结果:
Benchmark Mode Cnt Score Error Units
PowerOfTenBenchmark.mathPow thrpt 15 24.134 ± 32.132 ops/us
PowerOfTenBenchmark.arrayLookup thrpt 15 515.684 ± 10.056 ops/us
PowerOfTenBenchmark.switchLookup thrpt 15 461.318 ± 4.941 ops/us
所以#2 数组查找是最快的,确认接受的答案是正确的。
如果您认为 POWERS_OF_TEN
数组字面值初始化器很丑陋(我同意),还有一种更短且可能更不容易出错的方法:
private static final long[] POWERS_OF_TEN = IntStream.range(0, 16)
.mapToLong(i -> (long) Math.pow(10, i)).toArray();