java - 为什么从用户输入中解析出的最大可测试整数为字符串 (10^8)-1?

标签 java string casting type-conversion

一次接受用户输入一个字符,在我必须限制输入之前可接受的最大整数似乎是(10^8)-1。我有点惊讶它不是 Integer.MAX_VALUE为什么不是吗?

在扩展 KeyAdapter 的 Keyboard 类中编写的代码:

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class Keyboard extends KeyAdapter{
    private final int MAX_TESTABLE = 99999999;
    private final int VK_NUMBER = 48; //ASCII 0 starts here
    private final int VK_NUMBERPAD = 96; //ASCII numberpad offset

    public void keyPressed(KeyEvent e){
        int key = e.getKeyCode();

        if(((char)key == '0' ||
            (char)key == '1' ||
            (char)key == '2' ||
            (char)key == '3' ||
            (char)key == '4' ||
            (char)key == '5' ||
            (char)key == '6' ||
            (char)key == '7' ||
            (char)key == '8' ||
            (char)key == '9')){
            if(Integer.parseInt(Launcher.inputString+(char)key) <= MAX_TESTABLE){
                Launcher.inputString += (char)key;
            }
        }else if (e.getKeyLocation() == KeyEvent.KEY_LOCATION_NUMPAD){
            if(Integer.parseInt(Launcher.inputString+(char)(VK_NUMBER+key-VK_NUMBERPAD)) <= MAX_TESTABLE){
                Launcher.inputString += (char)(VK_NUMBER+key-VK_NUMBERPAD);
            }
        }

        System.out.println(
            "Key "+key+" pressed\n"+
            "Input string: "+Launcher.inputString
        );
    }
}

此处链接的其他类(class):

最佳答案

编辑:这就是 Vaysym 发现的最终解决方案。我将其粘贴在这里,以便将来可能查找此内容的任何人都更容易:

The answer is in the question: (10^8)-1

Here's why:

In Java, the primitive type int is allowed 4 bytes of memory: 2^32. Because it is signed, we have to allocate half of the 32 bits for the negative spectrum. We also have to subtract one from the total (which, because it's an odd number, happens to actually subtract from the positive spectrum). So our total range becomes (2^(32-1))-1 = 2,147,483,647

Because we are testing USING int here, this is the maximum testable number. So on the right operand the most we can check for is (2^31)-1, so we get this code: if(Integer.parseInt(inputString+(char)key) < 2147483647){}

This will still throw an exception because the left operand can end up being higher than Integer.MAX_VALUE, so we have to limit inputString before it gets there. Because the input is received one character at a time and the largest digit you can input, 9, is greater than the left-most digit of (2^31)-1, which is a 2, the closest we can get to Integer.MAX_VALUE is an entire order of magnitude short; Integer.MAX_VALUE has 10 digits, so we cannot test further than 9 digits: (10^(10-1))-1 = (10^9)-1 = 999,999,999

Because we're testing inputString plus the next inputted digit, we have to go down another order of magnitude, bringing us to the final answer of (10^8)-1

Final code: if(Integer.parseInt(inputString+(char)key) < 999999999){}

--------------------------------

原始答案:

您如何使用 Integer.parseInt 的问题是(引用 self 的评论):

If you pass in a value larger then 2147483647 to Integer.parseInt(), it will throw the exception before it can even compare it to < 2147483647, because you're already trying to assign a value to large for a Integer in your call to parseInt().

如果您传入 2147483647 以下的数字以外的任何内容(包括空字符串),都会引发异常。

要解决此问题,请尝试使用 try-catch block :

        try
        {
            Integer.parseInt(inputString);
            //No exception thrown, this is a valid Integer!
        }
        catch(NumberFormatException e)
        {
            //NumberFormatException! "inputString" Can not be an Integer!
        }

如果 Integer.parseInt() 抛出异常,catch 中的代码块将运行,否则 try 中的代码块将继续运行。通过捕获异常,不会导致程序崩溃

如果您不想使用 try/catch,则只需限制用户可以键入的内容即可。您可以使用LongparseLong而不是Integer允许更大的数字,但如果您输入非数字,仍然会引发异常。

更新:您可以使用它来检查输入字符串是否适合整数(如果数字小于长整型,则可能),但不幸的是,如果您输入的内容不是数字,它仍然会抛出异常。

    if(Long.parseLong(inputString+(char)key) > 2147483647)
    {
        //"inputString+(char)key" Will fit into an Integer!
        inputString += (char)key;
    }
    else
    {
        //"inputString+(char)key" Will NOT fit into an Integer!
    }

更新 2:查看您的编辑,您已经非常接近了。发生的情况是,当您添加字符时,它会被添加到字符串的末尾,然后对其执行parseInt。因此,将字符串“999999999”添加到 char(假设它的值为 1)将等于 9999999991(或转换为数字时为 9,999,999,991)而不是 1,000,000,000。当对其执行 parseInt() 时,该数字将大于 Integer。

另外,类型转换 intchar将打印出与 int 对应的 ASCII 字符的号码,参见this question了解更多信息。

要获得您正在寻找的输出,请尝试强制转换 inputStringkey 将它们添加在一起之前。示例:(使用 inputString = 50key = 50 )

Integer.parseInt(inputString) + (int)key    // = 100

而不是:

Integer.parseInt(inputString+(char)key)      // Would equal 5050, but because 50 is the ASCCI character for 2, it will be 502.

请注意,如果您尝试解析大于 2147483647 的数字,这仍然会引发异常,因此请考虑使用 try/catch block 将其括起来。

希望这可以帮助您了解正在发生的事情。

关于java - 为什么从用户输入中解析出的最大可测试整数为字符串 (10^8)-1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40570050/

相关文章:

java - 使用 JPA 时如何高效地找出新对象自动生成的 ID?

java - String.format() 在 Java 中格式化 double

c# - 删除字符串中的所有英文字母

c++ - 解析定界字符串

c++ - 为什么左值转换有效?

c++ - 将 vector 值复制到 char*

java - 隐藏多个空 TextView

java - JWS 启动时 PropertyPermission 访问被拒绝

string - 从多个变量创建自定义PowerShell对象

java - 从 TypeReference<E> 转换为 Class<E> 而无需强制转换 (Java)