从长变量中获取第二个数字[重复]

Posted

技术标签:

【中文标题】从长变量中获取第二个数字[重复]【英文标题】: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,这是预期的,但是当循环完成时firstDigit49。 有点困惑为什么。

【问题讨论】:

如果只需要第二个数字,为​​什么还需要循环? 第二位在哪个计算系统中?十六进制、十进制、八进制、二进制、...? 相关:What does '0' do in Java? 每当我问一个被标记为重复的问题时,我都会被左、右和中间(当然还有)否决。那么,这个是怎么得到九票的呢? 您似乎以long 变量开头?为什么要把它变成一个字符串? 【参考方案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_10num - 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

这是因为您的 firstDigitint。把它改成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 而不是数字的原因。

【讨论】:

以上是关于从长变量中获取第二个数字[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从Java中的int获取数字的特定数字[重复]

为啥有第二个变量指向 map() 函数,变量 student 来自哪里[重复]

数字的第二个根最多为小数点后4位[重复]

第二个参数是获取shell脚本函数中第一个参数的内容[重复]

在bash中创建一个循环脚本,其中2个变量递增,第二个变量根据第一个变量[重复]

如何在javascript中维护父变量值[重复]