当前位置: 首页 > 知识库问答 >
问题:

更快地找出一个数字是否以2开头的方法?

徐承载
2023-03-14

在Java中,如果给定的整数是以数字2开头的,而不需要将数字转换成字符串,那么最快的方法是什么?

String.valueOf(number).charAt(0) == '2'

共有3个答案

琴英华
2023-03-14

我很想做这样的事情:

  x = Math.abs(x);
  if ( ((int) Math.floor(x / Math.pow(10, Math.floor(Math.log10(x))))) == 2 )
  {
     ... // x equals 2
  }
姚浩歌
2023-03-14

我将各种解决方案相互对立:

public class FirstDigit
{
  static int digit;
  @GenerateMicroBenchmark public void string() {
    for (int i = 200_000_000; i < 400_000_000; i += 999961)
      digit = Integer.toString(i).charAt(0);
  }
  @GenerateMicroBenchmark public void math() {
    for (int i = 200_000_000; i < 400_000_000; i += 999961) {
      digit = (int) floor(i / pow(10, floor(log10(i))));
    }
  }
  @GenerateMicroBenchmark public void divide() {
    for (int i = 200_000_000; i < 400_000_000; i += 999961) {
      int x = i;
      while (x > 10) x /= 10;
      digit = x;
    }
  }
  @GenerateMicroBenchmark public void brokenDivide() {
    for (int i = 200_000_000; i < 400_000_000; i += 999961) {
      int x = i;
      while (x > 10) x >>= 3;
      digit = x;
    }
  }
  @GenerateMicroBenchmark public void bitTwiddling() {
    for (int i = 200_000_000; i < 400_000_000; i += 999961) {
      digit = i/powersOf10[log10(i)];
    }
  }
  @GenerateMicroBenchmark public boolean avoidDivide() {
    boolean b = true;
    for (int i = 200_000_000; i < 400_000_000; i += 999961) {
      b ^= firstDigitIsTwo(i);
    }
    return b;
  }


  private static final int[] log256 = new int[256];
  static {
    for (int i = 0; i < 256; i++) log256[i] = 1 + log256[i / 2];
    log256[0] = -1;
  }
  private static int powersOf10[] = {1, 10, 100, 1000, 10_000, 100_000,
    1_000_000, 10_000_000, 100_000_000, 1_000_000_000};

  public static int log2(int v) {
    int t, tt;
    return ((tt = v >> 16) != 0)?
        (t = tt >> 8) != 0 ? 24 + log256[t] : 16 + log256[tt]
      : (t = v >> 8) != 0 ? 8 + log256[t] : log256[v];
  }
  public static int log10(int v) {
    int t = (log2(v) + 1) * 1233 >> 12;
    return t - (v < powersOf10[t] ? 1 : 0);
  }

  static final int [] limits = new int[] {
    2_000_000_000, Integer.MAX_VALUE,
    200_000_000, 300_000_000-1,
    20_000_000, 30_000_000-1,
    2_000_000, 3_000_000-1,
    200_000, 300_000-1,
    20_000, 30_000-1,
    2000, 3000-1,
    200, 300-1,
    20, 30-1,
    2, 3-1,
  };
  public static boolean firstDigitIsTwo(int v) {
    for ( int i = 0; i < limits.length; i+= 2) {
      if ( v > limits[i+1] ) return false;
      if ( v >= limits[i] ) return true;
    }
    return false;
  }
}

以及结果:

Benchmark                   Mode Thr    Cnt  Sec         Mean   Mean error    Units
FirstDigit.avoidDivide     thrpt   1      3    5     2324.271       58.145 ops/msec
FirstDigit.bitTwiddling    thrpt   1      3    5      716.453        6.407 ops/msec
FirstDigit.brokenDivide    thrpt   1      3    5      578.259        7.534 ops/msec
o.s.FirstDigit.divide      thrpt   1      3    5      125.509        2.323 ops/msec
o.s.FirstDigit.string      thrpt   1      3    5       78.233        2.030 ops/msec
o.s.FirstDigit.math        thrpt   1      3    5       14.226        0.034 ops/msec
  • 数学方法显然是个失败者
  • string方法比math方法快六倍
  • 最简单的除法算法比这个算法快60%
  • OldCurmudgeon的比特旋转算法比除法快六倍
  • OldCurmudgeon的特殊casedavoidDivide方法(它直接给出是/否的答案,不像所有其他方法,它实际上决定了第一个数字)比位加法算法快三倍,是无可争议的赢家
  • 对于诊断,我还提供了一个brokenDividealgo。它不是除以10,而是除以3,给出了错误的答案。重点是强调divide算法的瓶颈是:brokenDividedivide快4.6倍,比比特旋转慢0.2倍

请注意,我使用了相当大的数字;相对速度随震级而变化。

和谦
2023-03-14

如果您想避免将其转换为字符串,您可以继续除以10以找到最有效的数字:

int getMostSignificantDigit(int x)
{
    // Need to handle Integer.MIN_VALUE "specially" as the absolute value can't
    // represented. We can hard-code the fact that it starts with 2 :)
    x = x == Integer.MIN_VALUE ? 2 : Math.abs(x);
    while (x >= 10)
    {
        x = x / 10;
    }
    return x;
}

我不知道这是否会比Husman的log/pow方法更快。

 类似资料:
  • 问题内容: 我正在制作一个程序,要求至少每秒捕获24个屏幕截图。目前,使用下面的代码,我每94毫秒仅获得1个,因此大约为10毫秒。 我不想使用任何第三方库,因为我试图将其保持尽可能小,但是如果我希望获得显着的性能提升,我会愿意的。我也试图保持该平台独立,但是,如果确实能够显着提高性能,我愿意将其限于Windows。 编辑:我现在也尝试了两种不同的方法;使用在oracles网站上找到的代码段,并在下

  • 问题内容: 我正在尝试编写一种方法,该方法将计算两个数字是否是赋值的相对质数。我主要是在寻找从哪里开始的答案。我知道有一种方法可以为我做很多事情,但是赋值几乎使我无需使用gcd或数组就可以做到。 我有点开始了,因为我知道我将不得不在for循环中使用运算符。 显然,此方法仅将返回,或者因为该函数仅将根据这两个数字是否相对质数来打印特定行。 我想我可能不得不写两个循环,无论是和,可能还有一些类型的语句

  • 问题内容: 我想知道如何检查Python中字符串是否以“ hello”开头。 在Bash中,我通常这样做: 如何在Python中实现相同的目标? 问题答案: 有关的更多信息。

  • 问题内容: 是否在名称以数字开头的CSS类无法正常工作的地方引用了它?例如,我发现一个背景类似的类: 不能在我拥有的大多数浏览器中工作,并且CSS语法显示该问题,但是我的问题是是否存在一种使以数字开头的名称的CSS类有效的 解决方法 ?。 问题答案: 没有CSS类。从逻辑上讲,该问题分为两个问题:可以在HTML中以数字开头的类名吗?(如果答案是“是”,则是这样),如果可以,您如何在CSS中使用相应

  • 问题内容: 我有以下if语句: 我希望它包含 等。使用字符串时是否有一种简单的方法?我试过了,但是没有用。 问题答案: 您的意思是: 或者您可以使用正则表达式:

  • 我想检查以开头的字符串是否正确。没有循环我怎么做?提前谢谢。