【问题标题】:Getting the second digit from a long variable [duplicate]从长变量中获取第二个数字[重复]
【发布时间】:2018-06-07 03:02:29
【问题描述】:

我正在尝试从长变量中获取第二个数字。

long mi = 110000000;
int firstDigit = 0;
String numStr = Long.toString(mi);
for (int i = 0; i < numStr.length(); i++) {
    System.out.println("" + i + " " + numStr.charAt(i));
    firstDigit =  numStr.charAt(1);
}

当我在控制台上打印firstDigit = numStr.charAt(1) 时。我得到1,这是预期的,但是当循环完成时firstDigit 有49。 有点困惑为什么。

【问题讨论】:

  • 如果只需要第二个数字,为​​什么还需要循环?
  • 第二位在哪个计算系统中?十六进制、十进制、八进制、二进制、...?
  • 每当我问一个被标记为重复的问题时,我都会被左、右和中间(当然还有)否决。那么,这个是怎么得到九票的呢?
  • 您似乎以long 变量开头?为什么要把它变成一个字符串?

标签: java long-integer


【解决方案1】:

因为 49 是 char '1' 的 ASCII 值。

因此您不应该直接将 char 分配给 int。

而且你不需要一个循环来不断地用charAt(1) 覆盖当前值。

int number = numStr.charAt(1) - '0'; // substracting ASCII start value 

上面的语句在内部像 49 -48 一样工作,给你 1。

如果您觉得这很混乱,就像其他人所说的那样,请使用Character.getNumericValue();

或者,虽然我不喜欢""+ hack,但下面应该可以工作

int secondDigit = Integer.parseInt("" + String.valueOf(mi).charAt(1));

【讨论】:

    【解决方案2】:

    你很困惑,因为 49 是整数 1 的 ASCII 值。所以你可以将字符解析为整数,然后你可以看到整数值。

        Integer.parseInt(String.valueOf(mi).charAt(1)):
    

    【讨论】:

    • 为了防止The method parseInt(String) in the type Integer is not applicable for the arguments (char),你应该使用Integer.parseInt(String.valueOf(mi).charAt(1)+"");之类的东西
    【解决方案3】:

    您可能正在寻找 Character.getNumericValue(...) 即

    firstDigit = Character.getNumericValue(numStr.charAt(1));
    

    否则,由于变量 firstDigit 的类型为 int,这意味着您分配的 ASCII representation of the character '1' 是 49,而不是指定索引处的整数。

    另外,请注意,由于您只对特定数字感兴趣,因此无需将语句 firstDigit = numStr.charAt(1); 放入循环中。

    相反,只需在循环外执行以下操作。

    int number = Character.getNumericValue(numStr.charAt(1));
    

    【讨论】:

      【解决方案4】:

      您只需要将 firstDigit 定义为 char 类型变量,因此将打印为字符。 由于您定义为 int 变量,因此它的值是 char '1': 49 的 ASCII 值。这就是为什么您得到 49 而不是 1。

      【讨论】:

        【解决方案5】:

        答案Integer.parseInt(String.valueOf(mi).charAt(1)+""); 是正确的。

        但是,如果我们想在我们的程序中考虑性能,我们需要一些改进。

        我们必须使用耗时的方法,Integer.parseInt() 和 String.valueOf()。而且自定义方法总是比Integer.parseInt() 和String.valueOf() 快得多。见simple benchmarks。

        因此,高性能解决方案可以如下所示:

        int y=0;
        while (mi>10)
        {
            y=(int) (mi%10);
            mi=mi/10;
        }
        System.out.println("Answer is: " + y);
        

        测试它:

        long mi=4642345432634278834L;
        int y=0;
        
        long start = System.nanoTime();
        
        //first solution
        //y=Integer.parseInt(String.valueOf(mi).charAt(1)+"");      
        
        //seconf solution
        while (mi>10)
        {
            y=(int) (mi%10);
            mi=mi/10;
        }
        
        long finish = System.nanoTime();
        
        long d = finish - start;
        System.out.println("Answer is: " + y + " , Used time: " + d);
        
        //about 821 to 1232 for while in 10 runs
        //about 61225 to 76687 for parseInt in 10 runs
        

        【讨论】:

        • 如果我们想考虑性能,我们绝对应该使用(num / 10^{Log_10{num} - 1}) % 10 而不是那个循环。这比其他替代方案要快得多,但对于我敢打赌的大多数人来说,乍一看并不是很明显。
        • java中没有^函数(仅用于位操作),我们应该使用Pow()方法,在这种情况下我们应该使用parseInt()等转换。它们在 java 中非常耗时。
        • 这不应该是真正的Java代码,更多的是用LaTeX来写数学公式。
        • @Voo 完全错误。 Log10 和/或 10^ 很优雅,但在数值上非常昂贵的浮点函数。由于浮点舍入,它们也不是 100% 准确。
        【解决方案6】:

        对数字进行字符串操作几乎总是错误的方法。

        要获得第二个数字,请使用以下内容;

        int digitnum = 2;
        
        int length = (int)Math.log10(mi));
        int digit = (int)((mi/Math.pow(base,length-digitnum+1))%base);
        

        如果您想要一个不同于第二个更改 digitnum 的数字。

        为了避免浮点数的不确定性,您可以使用整数数学库,例如 guava IntMath

        【讨论】:

        • 虽然在数学上是正确的答案,但我承认在考虑浮动误差时,我无法证明这给出了正确的答案。
        • @Voo 答案已更新为仅使用 log10,参考番石榴作为纯 int 基础替代方案。
        【解决方案7】:

        我们来看看

        System.out.println(numStr.charAt(1));
        firstDigit =  numStr.charAt(1);
        System.out.println(firstDigit);
        

        结果不会和你得到的一样

        1
        49
        

        这是因为您的 firstDigit 是 int。把它改成char,你会得到预期的结果

        【讨论】:

          【解决方案8】:

          你也可以像下面这样,

          firstDigit = Integer.parseInt( numStr.charAt(1)+"");
          

          所以它会打印长号的第二个数字。

          【讨论】:

            【解决方案9】:

            一些还没有提到的东西:

            • 整数数据类型的第二个数字是 undefined 如果长数字是 0-9(不,它不是零。整数没有小数位,这仅适用于浮点数点数。即使那样,您也必须为 NaN 或无穷大值返回 undefined)。在这种情况下,您应该返回一个哨兵,例如-1 表示没有第二个数字。

            • 使用 log10 来获取特定数字看起来很优雅,但它们是 1. 数字上最昂贵的函数之一,并且 2. 在边缘情况下经常给出不正确的结果。后面我会给出一些反例。

            性能可以进一步提高:

            public static int getSecondDigit(long value) {
            long tmp = value >= 0 ? value : -value;
            if (tmp < 10) {
              return -1;
            }
            
            long    bigNumber = 1000000000000000000L;
            boolean isBig     = value >= bigNumber;
            
            long  decrement   = isBig ? 100000000000000000L : 1;
            long  firstDigit  = isBig ? bigNumber : 10;
            int   result      = 0;
            if (!isBig) {
              long test = 100;
            
              while (true) {
                if (test > value) {
                  break;
                }
                decrement = firstDigit;
                firstDigit = test;
                test *= 10;
              }
            }
            
            
            
            // Remove first
            while (tmp >= firstDigit) {
              tmp -= firstDigit;
            }
            
            // Count second
            while (tmp >= decrement) {
              tmp -= decrement;
              result++;
            }
            
            return result;
            }
            

            比较: 1 000 000 个随机多头

            String.valueOf()/Character.getNumericValue():106 毫秒
            Taemyr 的日志/Pow:151 毫秒
            @Gholamali-Irani 的 Div10:45 毫秒
            上面的例程:30 毫秒

            这还没有结束,查表可以更快 递减 1/2/4/8、10/20/40/80 并避免使用乘法。

            【讨论】:

            • 非常好的比较
            【解决方案10】:

            试试这个以获得你的长的第二个字符

            mi.toString().charAt(1);
            

            【讨论】:

              【解决方案11】:

              如何获取 ASCII 码

              int ascii = 'A';
              int ascii = 'a';
              

              因此,如果您将字符分配给整数,则该整数将保存该字符的ASCII 值。在这里,我明确给出了值,在您的代码中,您正在调用一个返回字符的方法,这就是您得到 ASCII 而不是数字的原因。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-07-27
                • 1970-01-01
                • 2012-08-06
                • 2014-09-09
                相关资源
                最近更新 更多