从长变量中获取第二个数字[重复]
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
,这是预期的,但是当循环完成时firstDigit
有49
。
有点困惑为什么。
【问题讨论】:
如果只需要第二个数字,为什么还需要循环? 第二位在哪个计算系统中?十六进制、十进制、八进制、二进制、...? 相关: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
这是因为您的 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
而不是数字的原因。
【讨论】:
以上是关于从长变量中获取第二个数字[重复]的主要内容,如果未能解决你的问题,请参考以下文章
为啥有第二个变量指向 map() 函数,变量 student 来自哪里[重复]
第二个参数是获取shell脚本函数中第一个参数的内容[重复]