从长变量中获取第二个数字
Getting the second digit from a long variable
我正在尝试从一个 long 变量中获取第二个数字。
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
。
有点不明白为什么。
您可能正在寻找 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));
因为 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));
你只需要将firstDigit定义为一个char类型的变量,这样就会打印成字符。
因为你定义为 int 变量,它的值是 char '1' 的 ASCII 值:49。这就是你得到 49 而不是 1 的原因。
你感到困惑,因为 49 是整数 1 的 ASCII 值。所以你可以将字符解析为整数,然后你可以看到整数值。
Integer.parseInt(String.valueOf(mi).charAt(1)):
试试这个来获取 long 的第二个字符
mi.toString().charAt(1);
一起来看看
System.out.println(numStr.charAt(1));
firstDigit = numStr.charAt(1);
System.out.println(firstDigit);
结果与你得到的不一样
1
49
发生这种情况是因为您的 firstDigit 是 int。将其更改为 char,您将得到预期的结果
How to get ASCII code
int ascii = 'A';
int ascii = 'a';
因此,如果您将一个字符分配给一个整数,该整数将保存该字符的 ASCII
值。在这里我明确地给出了值,在你的代码中你调用了一个 returns 一个字符的方法,这就是你得到 ASCII
而不是数字的原因。
您也可以按照下面的方式进行,
firstDigit = Integer.parseInt( numStr.charAt(1)+"");
因此它将打印长数字的第二个数字。
答案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
通过字符串操作来处理数字几乎总是错误的方法。
要获得第二个数字,请使用以下命令;
int digitnum = 2;
int length = (int)Math.log10(mi));
int digit = (int)((mi/Math.pow(base,length-digitnum+1))%base);
如果你想要一个不同于第二个数字的数字。
为了避免浮点数的不确定性,您可以使用像 guavas 这样的整数数学库 IntMath
还没有提到的一些东西:
整数数据类型的第二个数字是 undefined 如果长数是 0-9(不,它不是零。整数没有小数位, 这只对浮点数是正确的。即便如此你必须 return undefined 对于 NaN 或无穷大值)。在这种情况下,您应该 return 一个哨兵,例如-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 毫秒
Log/Pow 泰米尔:151 毫秒
@Gholamali-Irani 的 Div10:45 毫秒
以上例程:30 毫秒
这还没有结束,通过查找表可以更快
递减 1/2/4/8, 10/20/40/80 并避免使用乘法。
我正在尝试从一个 long 变量中获取第二个数字。
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
。
有点不明白为什么。
您可能正在寻找 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));
因为 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));
你只需要将firstDigit定义为一个char类型的变量,这样就会打印成字符。 因为你定义为 int 变量,它的值是 char '1' 的 ASCII 值:49。这就是你得到 49 而不是 1 的原因。
你感到困惑,因为 49 是整数 1 的 ASCII 值。所以你可以将字符解析为整数,然后你可以看到整数值。
Integer.parseInt(String.valueOf(mi).charAt(1)):
试试这个来获取 long 的第二个字符
mi.toString().charAt(1);
一起来看看
System.out.println(numStr.charAt(1));
firstDigit = numStr.charAt(1);
System.out.println(firstDigit);
结果与你得到的不一样
1
49
发生这种情况是因为您的 firstDigit 是 int。将其更改为 char,您将得到预期的结果
How to get ASCII code
int ascii = 'A';
int ascii = 'a';
因此,如果您将一个字符分配给一个整数,该整数将保存该字符的 ASCII
值。在这里我明确地给出了值,在你的代码中你调用了一个 returns 一个字符的方法,这就是你得到 ASCII
而不是数字的原因。
您也可以按照下面的方式进行,
firstDigit = Integer.parseInt( numStr.charAt(1)+"");
因此它将打印长数字的第二个数字。
答案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
通过字符串操作来处理数字几乎总是错误的方法。
要获得第二个数字,请使用以下命令;
int digitnum = 2;
int length = (int)Math.log10(mi));
int digit = (int)((mi/Math.pow(base,length-digitnum+1))%base);
如果你想要一个不同于第二个数字的数字。
为了避免浮点数的不确定性,您可以使用像 guavas 这样的整数数学库 IntMath
还没有提到的一些东西:
整数数据类型的第二个数字是 undefined 如果长数是 0-9(不,它不是零。整数没有小数位, 这只对浮点数是正确的。即便如此你必须 return undefined 对于 NaN 或无穷大值)。在这种情况下,您应该 return 一个哨兵,例如-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 毫秒
Log/Pow 泰米尔:151 毫秒
@Gholamali-Irani 的 Div10:45 毫秒
以上例程:30 毫秒
这还没有结束,通过查找表可以更快 递减 1/2/4/8, 10/20/40/80 并避免使用乘法。