Why doesn't hasNextInt() method work for large integers? - java

I'm writing a simple program which receives integer inputs from a Scanner object, determines whether it's a palindrome or not, and returns the boolean value.
For most numbers, it works well. However, at this code snippet:
private static void programRunner() {
System.out.print("Insert your number:");
Scanner in = new Scanner(System.in);
if (in.hasNextInt()) {
int testNumber = in.nextInt();
boolean result = palindromeTester(testNumber);
System.out.println(result);
programRunner();
} else {
System.exit(0);
}
}
I added the "System.exit(0)" expression to make users easily terminate the program by intentionally typing any non-integer value. The problem is that when "considerably large" integers, such as "1234567654321," are provided, the code launches System.exit(0) which means it's not recognized as an integer?
I believe it's the problem lies in the "default radii" of the hasNextInt method, which probably limits the size of integer values it recognizes. (The program runs fine up to 9-digit integers) But I'm not sure. Or is there something wrong with the recursion?

Because an int in Java is 32 bit and can only hold 2^31 - 1 (2147483647) as maximum value (see also Integer.MAX_VALUE).
Anything bigger than that is not int, but long (except if it's even bigger than Long.MAX_VALUE, in which case you need to get the value as BigInteger.)
See Integer.MAX_VALUE, Long.MAX_VALUE,
Scanner.nextInteger(), Scanner.nextLong(),
Scanner.nextBigInteger() and BigInteger.

You can use nextLong() if you have larg "long" integers to read like so :
private static void programRunner() {
System.out.print("Insert your number:");
Scanner in = new Scanner(System.in);
if (in.hasNextLong())
{
long testNumber = in.nextLong();
boolean result = palindromeTester(testNumber);
System.out.println(result);
programRunner();
}
else
{
System.exit(0);
}
}

It seems that you've exceeded the range limit for the int type. the long type seems like what you're looking for.
So, you can either use the hasNextLong() and nextLong() methods of the Scanner class or as #Hovercraft Full Of Eels has suggested in the comments since you're not using the data in a numerical way, it may be better to receive the data as a String instead.
Lastly, but not least I find it inefficient to use recursion here as each recursive call creates a new stack frame along with that for each recursive invocation you're newing up a Scanner instance. it's better to use a while loop instead.

Related

How can we write method to read integers from a Scanner stream?

My goal is to implement a method named add that receives a reference to a Scanner object associated with a stream of input consisting of integers only. The method reads all the integers remaining to be read from the stream and returns their sum.
So if the input were 3 51 204 17 1040, the returned value would be 1315. The method must not use a loop of any kind (for, while, do-while t accomplish its job).
My attempt is shown below:
public void add(Scanner scanner){
Scanner input = new Scanner(System.input);
String s = input.nextLine();
String[] numbers = str.split(" ")
int[] ints = new int[numbers.length];
}
The specific issue that I am running into is the conversion of the string array into an integer array.
Since you can't use a loop of any kind, I think you are supposed to use recursion. You need to actually return a value. Presumably an int. Something like check if there is an int. If so, read it and recursively add any other int(s); Otherwise, return 0. Like,
public int add(Scanner input){
if (input.hasNextInt()) {
return input.nextInt() + add(input);
}
return 0;
}

No output from program to find all palindrome numbers within a given range

Create a java program to find and print all palindrome numbers within b and a
such that a<3000, b<3000and b<a.
My approach:-
import java.util.*;
class PalinDrome_Within_A_Range_Of_Two_Numbers{
public static void main(String args[]){
Scanner sc= new Scanner(System.in);
System.out.println("Enter an upper limit<3000");
int a=sc.nextInt();
System.out.println("Enter a lower limit <3000,upper limit");
int b=sc.nextInt();
int c=0;
int d,e,f,j;
for(int i=b;i<=a;i++){
j=(int)(Math.log10(i) + 1);
e=0;
f=0;
d=i;
for(int k=1;k<=j;k++){
f=i%10;
f=(int)(f*(Math.pow(10,(j-k))));
i=(i-(i%10))/10;
e=e+f;
}
if(e==d){
c=c+1;
System.out.println("The "+c+"th Palindrome number between "+b+" and "+a+" is "+d);
}
else{
break;
}
}
}
}
In this program, nothing appears in the output after giving the two integers.
The reason is that the first number, if it is not a palindrome, will end the loop at the else break; statement. To fix the problem, you should also not manipulate i within its loop, but rather a copy of it.
You may think about debugging. Shows you the point of failure faster than Stackoverflow.
Are you absolutely sour you enter uper limit before entering the lower limit because I by intuition added lower limit first and it did not work any way here is a simpler soultion if you want
public class PalinDrome_Within_A_Range_Of_Two_Numbers {
public static void main(String args[]){
Scanner sc= new Scanner(System.in);
System.out.println("Enter an upper limit<3000");
int a=sc.nextInt();
System.out.println("Enter a lower limit <3000,upper limit");
int b=sc.nextInt();
int c=0;
int d,e,f,j;
for(int i=b;i<=a;i++){
String num = String.valueOf(i);
String reversNum = getReversStr(num);
if(num.equals(reversNum)){
System.out.println(num);
}
}
}
private static String getReversStr(String num) {
char[] chars = num.toCharArray();
char[] revers = new char[chars.length];
for(int i = chars.length;i>0;i--)
revers[chars.length-i]=chars[i-1];
return new String(revers);
}
}
Others already suggested to use a debugger. That makes sense because your code is quite complicated. (By the way, you should keep the scope of your variables as small as possible to make your code more readable. It makes no sense to declare and initialize a variable outside a loop when it is used only inside the loop body.)
A better approach would be to simplify your code. You could split it into multiple functions and give each of these a meaningful name.
Or you could use a completely different approach. Being a palindrome is not so much a property of the number itself but of its string representation. So why not base the whole algorithm on strings:
for (int i = b; i <= a; i++) {
String num = String.valueOf(i);
String reverse = new StringBuilder(num).reverse().toString();
if (num.equals(reverse)) {
System.out.println(i);
}
}
I see two issues with your code (no guarantee that they are the only two, but solving them should get you a step further at the least).
You are using i as control variable in your outer loop, and then you are modifying i inside your inner loop (i=(i-(i%10))/10;). Since you are taking a copy of i into d anyway, there is a simple fix: do the modification on d instead of on i.
The break; statement in you else part will break out of the outer loop if the first number tried (b) is not a palindrome. I think you can just delete the else part.
I tried entering 102 as upper limit and 99 as lower. Your program correctly prints The 1th Palindrome number between 99 and 102 is 99, but then because i has been modified goes into an infinite loop. So you are on the way.
I agree with what others have said about breaking your code up in less comlex methods. This will also allow unit testing each method, which will help to locate bugs. Better variable names will help understanding the code, not least when you ask others to take a look. Finally, don’t declare a variable until you need it, this will also help readability.

Confusion with Scanners (Big Java Ex 6.3)

Currently reading Chapter 6 in my book. Where we introduce for loops and while loops.
Alright So basically The program example they have wants me to let the user to type in any amount of numbers until the user types in Q. Once the user types in Q, I need to get the max number and average.
I won't put the methods that actually do calculations since I named them pretty nicely, but the main is where my confusion lies.
By the way Heres a simple input output
Input
10
0
-1
Q
Output
Average = 3.0
Max = 10.0
My code
public class DataSet{
public static void main(String [] args)
{
DataAnalyze data = new DataAnalyze();
Scanner input = new Scanner(System.in);
Scanner inputTwo = new Scanner(System.in);
boolean done = false;
while(!done)
{
String result = input.next();
if (result.equalsIgnoreCase("Q"))
{
done = true;
}
else {
double x = inputTwo.nextDouble();
data.add(x);
}
}
System.out.println("Average = " + data.getAverage());
System.out.println("Max num = " + data.getMaximum());
}
}
I'm getting an error at double x = inputTwo.nextDouble();.
Heres my thought process.
Lets make a flag and keep looping asking the user for a number until we hit Q. Now my issue is that of course the number needs to be a double and the Q will be a string. So my attempt was to make two scanners
Heres how my understanding of scanner based on chapter two in my book.
Alright so import Scanner from java.util library so we can use this package. After that we have to create the scanner object. Say Scanner input = new Scanner(System.in);. Now the only thing left to do is actually ASK the user for input so we doing this by setting this to another variable (namely input here). The reason this is nice is that it allows us to set our Scanner to doubles and ints etc, when it comes as a default string ( via .nextDouble(), .nextInt());
So since I set result to a string, I was under the impression that I couldn't use the same Scanner object to get a double, so I made another Scanner Object named inputTwo, so that if the user doesn't put Q (i.e puts numbers) it will get those values.
How should I approach this? I feel like i'm not thinking of something very trivial and easy.
You are on the right path here, however you do not need two scanners to process the input. If the result is a number, cast it to a double using double x = Double.parseDouble(result) and remove the second scanner all together. Good Luck!

Adding unknown number of numbers to arraylist

I'm trying to make an Insertion Sort algorithm in Java, and I want it to read user input, and he/she can put however many numbers they wish (We'll say they're all integers for now, but long run it would be nice to be able to do both integers and doubles/floats), and I want the algorithm to sort them all out. My issue is that when I run this code to see if the integers are adding correctly, my loop never stops.
public class InsertionSort {
public static void main(String[] args){
System.out.println("Enter the numbers to be sorted now: ");
ArrayList<Integer> unsortNums = new ArrayList<Integer>();
Scanner usrIn = new Scanner(System.in);
while(usrIn.hasNextInt()) {
unsortNums.add(usrIn.nextInt());
System.out.println(unsortNums); //TODO: Doesn't stop here
}
sortNums(unsortNums);
}
}
Now, I suspect it has something to do with how the scanner is doing the .hasNextInt(), but I cannot for the life of me figure out why it isn't stopping. Could this be an IDE specific thing? I'm using Intellij Idea.
Let me know if I left anything out that I need to include.
Your code will stop as long as you stop adding numbers to your input stream. nextInt() is looking for another integer value, and if it can't find one, it'll stop looping.
Give it a try - enter in any sequence of characters that can't be interpreted as an int, and your loop will stop.
As a for-instance, this sequence will cease iteration: 1 2 3 4 5 6 7 8 9 7/. The reason is that 7/ can't be read as an int, so the condition for hasNextInt fails.
When using a scanner on System.in, it just blocks and waits for the user's next input. A common way of handling this is to tell the user that some magic number, e.g., -999, will stop the input loop:
System.out.println("Enter the numbers to be sorted now (-999 to stop): ");
List<Integer> unsortNums = new ArrayList<Integer>();
Scanner usrIn = new Scanner(System.in);
int i = usrIn.nextInt();
while(i != -999) {
unsortNums.add(i);
i = usrIn.nextInt();
}

How to compare a variable to see if it's the right class type?

I've been learning Java from scratch again since 2 years of rust, and I was playing around with a simple random generator code. My issue here is that when the user is asked what he wants as his highest die roll, it must be a number (int) class type.
I was trying to create an if statement and compare a variable to its class, rather than letting my IDE stop and show me an error message in a case the user typed letters.
Here is my code (It's the simplest code ever but it's safe to say that I'm new and motivating myself to learn Java again.) :
package firstguy;
import java.util.Random;
import java.util.Scanner;
public class randomnum {
public static void main(String[] args){
Random dice = new Random();
Scanner userin = new Scanner(System.in);
int number;
int highnum;
System.out.println("What's the highest roll you want? \n");
highnum = userin.nextInt();
for(int counter=1; counter<= highnum; counter++){
number= 1 + dice.nextInt(highnum);
System.out.println("This is the number " + number);
}
}
}
I want to be able to compare highnum, here to see if it stays as the class type int and not a letter. In case a letter or a character is typed, a message should be displayed or the question should be repeated. I've been trying to look for this problem but I keep getting results of comparing two variables of the same class type.
Is there no way to compare a variable to a class type?
Primitive types of Java do not have a class. Their wrapper types do, but your code does not use them.
What you are trying to do is to check end-user input for presence of character combinations that represent an integer vs. everything else. This is relatively easy to do, because Scanner provides methods hasNext... for various data types. You can use hasNextInt() in a loop, discarding the unwanted input, like this:
System.out.println("What's the highest roll you want? \n");
while (!userin.hasNextInt()) {
System.out.println("Please enter an integer.");
userin.nextLine();
}
// Since we reached this point, userin.hasNextInt() has returned true.
// We are ready to read an integer from the scanner:
highnum = userin.nextInt();
nextInt() (or most other nextXYZ methods, for that matter), throw an InputMismatchException if they encounter input that doesn't match their call (e.g., a letter in a nextInt call). So one option would be to simply catch it:
int highnum;
try {
highnum = userin.nextInt();
} catch (InputMismatchException e) {
System.out.println ("Wrong input encountered");
}
What you're looking for is not a way to "compare a variable to a class type", but rather to check a String to see if it has the right format. If you want to see if a String consists only of digits, the simplest way is using matches and a regular expression:
if (inputString.matches("\\d+")) {
... the input is valid
} else {
... complain
}
The regular expression here means "one or more digits". You could also use hasNextInt on a Scanner, or use nextInt on a Scanner and catch exceptions, or use Integer.parseInt(inputString) and catch exceptions, just to name a few.
try this:
boolean go = true;
System.out.println("What's the highest roll you want? \n");
while(go){
try{
highnum = userin.nextInt();
go = false;
catch(Exception e){
System.out.println("Please type in an integer: ");
highnum = userin.nextInt();
}
}

Categories