Java - Aromatic Numbers- inputting - java

An aromatic number is of the form AR, where each A is an Arabic digit, and each
R is a Roman numeral.
Each pair AR contributes a value described below, and by adding or
subtracting these values together we get the value of the entire aromatic number.
An Arabic digit A can be 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9. A Roman numeral R is one of the seven letters I, V, X, L, C, D, or M. Each Roman numeral has a base value:
This program is designed to take a AR value on the same line (inputted like e.g. 3V), and multiply it. 3V would be 3 x 5 = 15. Since V is 5.
My issue is that I cannot take what the user inputs and multiply an integer by a string. This makes it tedious. I tried converting the string into a int but the program gives me a nullformatException.
Also A would be in the first cell [0] and R (the numeral) in cell [1]
import java.io.*;
import java.util.*;
import java.text.*;
public class AromaticNumerals
{
public static int decode (String x) // since input is direct the program doesnt require validation
{
if (x.equals ("I"))
return 1;
else if (x.equals ("V"))
return 5;
else if (x.equals ("X"))
return 10;
else if (x.equals ("L"))
return 50;
else if (x.equals ("C"))
return 100;
else if (x.equals ("D"))
return 500;
else
return 1000;
}
public static void main (String str[])
throws IOException
{
BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
int Output;
int MAX = 20;
String[] x = new String [MAX]; // by picking an array we can separate the A-R
System.out.println ("Please input an aromatic number. (AR)");
x [0] = (stdin.readLine ());
int y = Integer.parseInt (x [0]);
Output = ( y * decode (x [1]));
System.out.println (Output);
}
}

int MAX = 20;
String[] x = new String [MAX]; // by picking an array we can separate the A-R
Incorrect. All of your input is going into the first element of the array, x[0]. You are confusing an array of strings with an array of characters. The simplest solution is to eliminate the String[] and use a plain String, then extract the individual characters with charAt() or substring().

stdin.readLine() is going to grab all the characters from the console and store them in the string found at x[0]. You're then attempting to parse an integer from the full string, not just the first character, this is why your call to parseInt is failing. Instead, call parseInt on the first character via parseInt(x[0].substring(0,1)) and pass the second character of the string to the decode method via decode(x[0].substring(1,2)). Also, if you don't need an array of strings, don't use one.

Did you by chance come from a C background? Or any other languages where string is a pointer to the first element of an array of characters? Java works differently in that respect, a Java string is first class object so x [0] = (stdin.readLine ()); reads the whole line into the first string so int y = Integer.parseInt (x [0]); will try to parse both A and R. Instead you want perhaps x[0].charAt(0) and x[0].charAt(1), also you don't need x to be an array.

Why you're getting errors:
When you read the user input here
x [0] = (stdin.readLine ());
... you are reading the whole aromatic number e.g. 4V or whatever, and you are putting it in the first index of your array x. Then,
int y = Integer.parseInt (x [0]);
Here you try to parse the first element of x as an integer. But you didn't just put the integer part of the aromatic number there, you put the whole thing. You'll get a NumberFormatException there, because the Integer class can't parse the letter character you're passing it along with the number. Then,
Output = ( y * decode (x [1]));
... you try to pass the second element of x to the decode method, but there's nothing there, because you put the entire string in x[0]. That's your NullFormatException, because x[1] is null.
To fix it:
String line = stdin.readLine();
int y = Integer.parseInt(line.charAt(0));
int output = y * decode(line.charAt(1));
or whatever.

Related

Java Hexadecimal to Decimal conversion: Custom Logic

I am trying to figure out how to convert hex into a string and integer so I can manipulate an RGB light on my arduino micro-controller through it's serialport. I found a good example on the java website, but I'm having a difficult time understanding some of the methods and I am getting hung up. I could easily just copy-paste this code and have it work but I want to fully understand it. I will add comments to my understandings and hopefully someone can provide some feedback.
public class HexToDecimalExample3{
public static int getDecimal(String hex){ //this is the function which we will call later and they are declaring string hex here. Can we declare string hex inside the scope..?
String digits = "0123456789ABCDEF"; //declaring string "digits" with all possible inputs in linear order for later indexing
hex = hex.toUpperCase(); //converting string to uppercase, just "in case"
int val = 0; //declaring int val. I don't get this part.
for (int i = 0; i < hex.length(); i++) //hex.length is how long the string is I think, so we don't finish the loop until all letters in string is done. pls validate this
{
char c = hex.charAt(i); //char is completely new to me. Are we taking the characters from the string 'hex' and making an indexed array of a sort? It seems similar to indexOf but non-linear? help me understand this..
int d = digits.indexOf(c); //indexing linearly where 0=1 and A=11 and storing to an integer variable
val = 16*val + d; //How do we multiply 16(bits) by val=0 to get a converted value? I do not get this..
}
return val;
}
public static void main(String args[]){
System.out.println("Decimal of a is: "+getDecimal("a")); //printing the conversions out.
System.out.println("Decimal of f is: "+getDecimal("f"));
System.out.println("Decimal of 121 is: "+getDecimal("121"));
}}
To summerize the comments, it's primarily the char c = hex.charAt(i); AND the val = 16*val + d; parts I don't understand.
Ok, let's go line for line
public static int getDecimal(String hex)
hex is the parameter, it needs to be declared there, so you can pass a String when you call the function.
String digits = "0123456789ABCDEF";
Yes, this declares a string with all characters which can occur in a hexadecimal number.
hex = hex.toUpperCase();
It converts the letters in the hex-String to upper case, so that it is consistent, i.e. you always have F and never f, no matter which is being input.
int val = 0;
This is the variable where the corresponding decimal value will later be in. We will do our calculations with this variable.
for (int i = 0; i < hex.length(); i++)
hex.length() is the number of characters in the hex-String provided. We execute the code inside this for loop once per character.
char c = hex.charAt(i);
Yes, char represents a single character. We retrieve the character from the hex-String at index i, so in the first iteration it is the first character, in the second iteration the second character and so on.
int d = digits.indexOf(c);
We look which index the character has in the digit-String. In that way we determine the decimal representation of this specific digit. Like 0-9 stay 0-9 and F becomes a 15.
val = 16*val + d;
Let's think about what we have to do. We have the decimal value of the digit. But in hexadecimal we have this digit at a specific position with which it gets multiplied. Like the '1' in '100' is actually not a 1, but 100 * 1 because it is at this position.
10 in hexadecimal is 16 in decimal, because we have 1 * 16. Now the approach here is a little bit complicated. val is not uninitialized. val is 0 at the beginning and then contains the cumulated values from the previous iterations. Since the first character in the String is the highest position we don't know directly with what we have to multiply, because we don't know how many digits the number has (actually we do, but this approach doesn't use this). So we just add the digit value to it. In the consecutive iterations it will get multiplied by 16 to scale it up to the corresponding digit base value. Let me show you an example:
Take 25F as hex number. Now the first iteration takes the 2 and converts it to a 2 and adds it to val. The 16 * val resolves to 0 so is not effective in the first time.
The next iteration multiplies the 2 with 16 and takes the 5 (converted to 5) and adds it to val. So now we have (I split it mathematically so you understand it):
2 * 16 + 5
Next we get the F which is decimal 15. We multiply val by 16 and add the 15.
We get 2 * 256 + 5 * 16 + 16 (* 1), which is actually how you calculate the decimal value of this hex value mathematically.
Another possibility to compute val is:
val += Math.pow(16, hex.length() - i - 1) * d;

Java - flipping an integer using String manipulation occasionally returning an error

This is part of a longer coding challenge - one part involves "flipping" the digits of an input number (i.e. 1234 becomes 4321) and removing leading zeros as applicable.
Below, I have written the method flipOpp that accomplishes this. Most of the time, it works perfectly. But sometimes, I'm getting an error because the last digit becomes a dash ("-") and obviously, the Integer.parseInt() method won't work if one of the digits is a dash!
Any ideas what might be causing this? Also, is there an easier way to flip the digits of an int? The method I'm using right now doesn't seem very efficient - turning an int to a String, then to a character array, manipulating the characters of this array, turning it back into a String, and finally back to an int.
Thanks! Code for this method is below:
// third operation: reverse the digits and remove leading zeros
public static int flipOpp(int num){
char temp;
// change int to a String
String stringNum = Integer.toString(num);
// change String to a char array of digits
char[] charNum = stringNum.toCharArray();
// flip each character and store using a char temp variable
for (int i=0;i<charNum.length/2;i++){
temp = charNum[i];
charNum[i]=charNum[charNum.length-i-1];
charNum[charNum.length-i-1]=temp;
}
// turn flipped char array back to String, then to an int
// this process removes leading zeros by default
String flipString = new String(charNum);
if (flipString.length()<7){
int flipInt = Integer.parseInt(flipString);
return flipInt;
}
else return 0;
}
Any ideas what might be causing this?
Definitely sounds like negative numbers
is there an easier way to flip the digits of an int? The method I'm using right now doesn't seem very efficient
Keep it as an integer. Don't worry about the negative
public static int flipOpp(int num) {
int reversed = 0;
while (num!=0) {
reversed = reversed*10 + num%10;
num /= 10;
}
return reversed;
}
For example, -50,
0*10+0=0
-50/10=-5
- -
0*10+(-5)=-5
-5/10=0
- -
END, output -5

how to prefix to a primitive data type

here i have a problem. i want a user to input some numbers, then i will convert the input into a string,i will then count the length of the string, and if it is less than 8,i want to add more zeros to the input to make it 8 so that i can do some staff with the number. i have tried to use decimalformat but its not working. plz help.
thanks in advance
int s=Integer.parseInt(s1.readLine());
String news=String.valueOf(s);
if(news.length()<8){
DecimalFormat myformat=new DecimalFormat("00000000");
String out= myformat.format(s);
int onth=(Integer.valueOf(out)).intValue();
s=onth;
}else{
System.out.format("your number is: %d\n",s);
Forget about using the DecimalFormat.
Change your format to the following
System.out.format("your number is: %08d\n",s)
The %08d will lead with zeros, to a width of 8.
This will only display the number in the format you've requested. As stated elsewhere in this thread, treating it as a number would remove the leading zeros.
If you want to store it in a String variable however, you can use
String intString = String.format("%08d", s);
to store it.
Update *
As you have a specific need to get a series of numbers between a substring
the following code will do what you want.
private static int getSubNumber(int startIndex, int stopIndex, int number) {
String num = String.format("%08d", number);
return Integer.parseInt(num.substring(startIndex, stopIndex));
}
If you pass in the number you want to convert, it will change it to a string, and then convert the substring between the two indexes you pass in back into a number
System.out.println(getSubNumber(2,5,12345678)); // = 345
System.out.println(getSubNumber(2,5,12345)); // = 12
System.out.println(getSubNumber(2,5,123)); // = 0
This is non inclusive, getSubNumber(2,5,...) gets values at position 2,3 and 4 NOT 5.
For your example of 144, use start index 2, stop index 6 for positions 2, 3, 4 and 5
System.out.println(getSubNumber(2,6,144)); // = 1
DecimalFormat is to format numbers in the way we give the pattern.
And to append zeros, please follow this:
Add leading zeroes to a string
If you need to add 0 after the value, you can multiply it by 10 pow the number of missing 0:
int result = Integer.parseInt(news);
if(news.length()<8){
int diff = 8 - news.length();
result = result * Math.pow(10, diff); // ==> result = result * 10^(8 - news.length())
}
I think that's the simpliest way to do that.
Edit Ahhh, yes... There is prefix in the question. Nevermind!
Even if you prefix an int with zeros the actual value will change to the original value. If you want padding you'll have to go with string. The out variable will give you the result.
Update based on comment
import java.util.Scanner;
public class SquareSubString {
public static void main(String[] args) {
String userInputSquare = getSquaredInput();
int digits2to5 = Integer.parseInt(userInputSquare.substring(2, 6));
System.out.println("Squre of digits 2 to 5 is : " + (digits2to5 * digits2to5));
}
private static String getSquaredInput() {
System.out.println("Enter a number : ");
Scanner in = new Scanner(System.in);
int input = in.nextInt();
in.close();
return String.format("%08d", (input * input));
}
}

Taking a string of numbers, chopping it up into groups of 5, and storing these values as an int array

Okay, I have a problem with taking numbers and storing them into an int array. I have the basic outline of the code, but I'm having trouble storing them in a way that displays when there is a 0 in front of a group of non-zero numbers.
For example, when I do this:
String s = "030142165109876";
private static void breakCode(String s){
int x = s.length(), m = 0, l = x/5;
String[] array = s.split("");
int[] output = new int[l+1];
int[] results = new int[array.length];
for(int i = 0; i < x/5; i++){
double y = 0;
if(i == 0){
for(int r = 5; r >= 0; r--){
try {results[m] = Integer.parseInt(array[m]);} catch (NumberFormatException nfe) {};
y = y + (Math.pow(10, r) * results[m]);
m++;
}
output[i] = (int) y;
System.out.println(output[i]);
}
if (i != 0){
for(int r = 4; r >= 0; r--){
try {results[m] = Integer.parseInt(array[m]);} catch (NumberFormatException nfe) {};
y = y + (Math.pow(10, r) * results[m]);
m++;
}
output[i] = (int) y;
System.out.println(output[i]);
}
}
}
The output for this code is:
3014
21651
9876
How do I get the zero to be held in place on the left hand side? I know it's because I'm using power functions and the leftmost value to that power wont show up when printing. Is there any way to force the int array to hold 5 digits so that when the number is less than 10000 it will hold the left most value as 0? The second line doesn't start with a 0 so it holds all 5 digits properly, but not the first and third (I wrote the numbers as an example, the real program uses randomized digits).
Full disclosure, this is for an assignment, but the programmatic methods I've thought up to solve this issue don't solve it. I have searched for my specific problem extensively throughout this website (trust me, I've grown to love searching through here), but I haven't picked up any useful tidbits regarding this specific problem. This is also my own way of solving the problem, and if there's a way of holding 5 digits for a place in an int array then I'd love to do it with my solution rather than having my friend's coding buddy come up with a really elegant solution that isn't my own brainchild.
Thank you
P.S. I'm very verbose
First split the input into strings 5 chars long, then parse them into ints:
String[] parts = str.split("(?<=\\G.{5})");
int[] nums = new int[parts.length];
for (int i = 0; i < parts.length; i++)
nums[i] = Integer.parseInt(parts[i]);
The regex for split() causes a split after every 5 chars - the \G (end of last match) ensures no overlap.
It's unclear what your exact problem is, but if it's just outputting the numbers with leading zeroes intact, I would just output parts and not bother with parsing them into an int[]. IF it's about outputting int values with leading zeroes, use
System.out.println(new DecimalFormat("00000").format(nums[i]));
Zeros in format patterns mean always print a digit there.
Numbers are always stored[1] and printed without zeroes by default. It is how Java (and almost all other languages) work.
If you just want to print 5 digits, consider printf.
printf("%05d\n", output[i]);
If you really want to always store 5 digits, use String[] and split using String methods. The substring method of String should do what you want easily.
[1] Conceptually (and in most, if not all, practical purposes) we treat numbers are stored without leading zeroes. In fact, strictly speaking, it does not. Java allocates some memory to store your numbers, and set this piece of memory with zeroes. As a whole memory piece, it does have leading zeroes, but the underlying processing throw these zeroes away, because this is how we understand numbers.

charAt() for integers greater than 1?

I am trying to create a program that displays the x and y coordinates of any given point, reflected across the linear function ax+b. However, I get a runtime error which says that it's out of bounds. I know you can't invoke methods on primitive data types, but I have no idea how else to get it.
import java.util.*;
public class ReflectivePoint {
public static void main (String[]args){
Scanner lol = new Scanner(System.in);
System.out.println("Please enter the linear function.");
//That will be in the format ax+b
String function = lol.nextLine();
Scanner lol2 = new Scanner(System.in);
System.out.println("Please enter the point.");
//That will be in the format a,b
String point = lol2.nextLine();
int a = point.charAt(1);
int b = point.charAt(3);
int m = function.charAt(1);
int c = function.charAt(4);
int x1 = (2 / (m + 1 / m)) * (c + b - a / m) - a;
int y1 = (-1/m) * x1 + a / m + b;
System.out.println(x1+", "+y1);
}
}
Perhaps you are getting a String of length 3, eg "1,2".
charAt(3) will try and return the 4th char of the String which doesn't exists so it throws an StringIndexOutOfBoundsException.
The index out of bounds error means "You have asked me for the 4th character of this string, but the string has fewer than 4 characters."
Note that (like most computer language indexes), the first character is 0. charAt("hello",1) == 'e'
You should check the length of the string before calling charAt(). Or, catch the exception and handle it.
charAt() probably isn't the best choice for your program, because it will only currently handle single-digits. Try String.split() to split the String on the comma.
Also, at the moment it's using the ASCII value of the character. That is (if you fixed the indexes) "a,b" would result in you doing your maths with m=97 and c=98. I guess that's not what you want. Find out about Integer.parseInt()
Aside from the out of bounds issue, which others have pointed out is you need to start at charAt(0) because the number is an offset into the char array (string), not getting the nth element.
You also need to subtract '0' to convert to an integer.
string point = "4";
int a = point.charAt(0);
//a=52 //not what you wanted
string point = "4";
int a = point.charAt(0) - '0';
//a=4 //this is what you wanted
You can use:
int a = point.charAt(0);
provided that that point is not empty.
Ideally you should perform a pre-use length check on the input String.

Categories

Resources