Why does this lead to an ArrayIndexOutOfBoundsException? - java

There is something that doesn't quite make sense to me. Why does this:
public static int[] countNumbers(String n){
int[] counts = new int[10];
for (int i = 0; i < n.length(); i++){
if (Character.isDigit(n.charAt(i)))
counts[n.charAt(i)]++;
}
return counts;
}
bring up an ArrayOutOfBounds error while this:
public static int[] countNumbers(String n){
int[] counts = new int[10];
for (int i = 0; i < n.length(); i++){
if (Character.isDigit(n.charAt(i)))
counts[n.charAt(i) - '0']++;
}
return counts;
}
does not? The only difference between the two examples is that the index for counts is being subtracted by zero in the second example. If I'm not mistake, shouldn't the first example display correctly since the same value is being checked?
Here are the value being passed for the two methods:
System.out.print("Enter a string: ");
String phone = input.nextLine();
//Array that invokes the count letter method
int[] letters = countLetters(phone.toLowerCase());
//Array that invokes the count number method
int[] numbers = countNumbers(phone);

This is the problem:
counts[n.charAt(i)]++;
n.charAt(i) is a character, which will be converted to an integer. So '0' is actually 48, for example... but your array only has 10 elements.
Note that the working version isn't subtracting 0 - it's subtracting '0', or 48 when converted to an int.
So basically:
Character UTF-16 code unit UTF-16 code unit - '0'
'0' 48 0
'1' 49 1
'2' 50 2
'3' 51 3
'4' 52 4
'5' 53 5
'6' 54 6
'7' 55 7
'8' 56 8
'9' 67 9
The code is still broken for non-ASCII digits though. As it can only handle ASCII digits, it would be better to make that explicit:
for (int i = 0; i < n.length(); i++){
char c = n.charAt(i);
if (c >= '0' && c <= '9') {
counts[c - '0']++;
}
}

'0' is quite different from 0. '0' is the code of the "zero" character.

problem is in the line counts[n.charAt(i)]. here n.charat(i) may return values larger than 9;

The confusion here is that you're thinking '0' == 0. This is not true. When treated as a number, '0' has the ASCII value for the character 0, which is 48.

Because n.charAt(i) returns a character which is then boxed to a number. In this case the character 0 is actually ASCII value 48.
By subtracting character '0', you are subtracting the value 48 and taking the index into a range that is 0-9 because you've checked the character is a valid digit.

Related

counting alphabetic characters between 'a' and 'z'

I came across a code which checks whether a character is between 'a' and 'z' case insensitive. However, I don't understand what the line after that is doing which is:
alphabets[c - 'a']++;
Could someone please explain this code to me?
alphabets = new int[26];
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if ('a' <= c && c <= 'z')
{
alphabets[c - 'a']++; // what does this do?
}
}
This code counts the number of times every lower-case letter appears in the strings. alphabets is an array where the first (i.e., index 0) index holds the number of as, the second the amount of bs, etc.
Subtracting a from the character will produce the relative index, and then ++ will increment the counter for that letter.
A char in Java is just a small integer, 16 bits wide. Generally speaking, the values it holds are the values that Unicode [aside: Java does not represent characters as "ASCII"] assigns to characters, but fundamentally, chars are just integers. Thus 'a' is the integer 0x0061, which can also be written as 97.
So, if you have value in the range 'a' to 'z', you have a value in the range 97 to 122. Subracting 'a' (subtracting 97) puts it in the range 0 to 25, which is suitable for indexing the 26-element array alphabets.

Sum Of Digits BigInteger

I was trying to find the sum of digits of a BigInteger and found this code.
BigInteger big = BigInteger.valueOf(2).pow(1000);
String digits = big.toString();
int sum = 0;
for(int i = 0; i < digits.length(); i++) {
int digit = (int) (digits.charAt(i) - '0');
sum = sum + digit;
}
System.out.println(sum);
I don't understand why - '0' is added in 6th line of the code.
int digit = (int) (digits.charAt(i) - '0');
If I remove that part it gives me a wrong answer.
For example sum of digits of 16 without - '0' gives 103 as the answer instead of 7.
So, can anyone explain the importance of that part in the code?
Any help is appreciated.
The code digits.charAt(i) gives you the ASCII code for the digit. So if you look at an ASCII table, you'll see the value of the character 7 is 55 and the value of character 0 is 48. If you subtract 0 from 7, you'll get 7, which is the digit you're looking for.
For example if you take a '5' from digits.getCharAt(i):
'5' - '0' = ?
According to the ASCII table Can be translated to:
53 - 48
Which is 5 and it's the result you're looking for

Negative string index

I am doing some kind of cipher in Java for schools homework. The task is to change the value of a certian char to a new one with a specific offset which is given by the user and has a range from negative numbers to positive numbers (alphabet).
Now I have a problem with negative offsets. I have created a String with the Alphabet which helps to find the new char. For example: With the offset of 7 I got this: encrypt(“TEST”) = “ALZA”. So my code grabs the index of the string value and searches with this index in the alphabet string for the new char. Anyway when I now have the char 'E' and a negative index i.e '-7' it will return the value of -3 for the new index of the new char (I hope that makes sense). Since there is no char on index '-3' I get an error.
So how can I access to the end of the string instead of going more and more into negative index numbers ?
Add 26 then mod 26:
i = (i + 26) % 26;
This always works for indexes down to -26. If that's not enough, just add some zeroes:
i = (i + 26000000) % 26;
Your general problem appears to be that letters are represented by only 26 indices, but the actual index variable you use might be greater than 26, or even less than zero (negative). One way to handle this problem is to use the mod operator to safely wrap your index around to always point to a range containing a valid letter.
Here is logic which can do that:
if (index < 0) {
index = (index % 26) + 26;
}
else {
index = index % 26;
}
Assuming the letter E is position 5 and you have a reassignment of -7, this would mean that the new index would be -2. This new position can be mapped using the above logic as follows, where index = -2 in this case:
5 - 7 = -2
(-2 % 26) + 26
-2 + 26
24
And character in position 24 is the letter X.
If you can constrain shift values to be positive, you can use remainder operator:
int newIndex = (index + shift) % 26
If there are negatives to be expected:
int newIndex = Math.floorMod(inndex + shift, 26) would do the trick
Actually you need mathematical modulo, but % operator is not quite that

Character subtraction in String

Here is the code snippet i am trying to figure out whats happening
String line = "Hello";
for (int i = 0; i < line.length(); i++) {
char character = line.charAt(i);
int srcX = 0;
if (character == '.') {
}else{
srcX = (character - '0') * 20;
System.out.println("Character is " + (character - '0') +" " + srcX);
}
}
and executing that code will result to this
Character is 24 480
Character is 53 1060
Character is 60 1200
Character is 60 1200
Character is 63 1260
How a character minus the string which is "0" result in integer?? and where does the system base its answer to have 24,53,60,60,63?
You are allowed to subtract characters because char is an integer type.
The value of a character is the value of its codepoint (more or less, the details are tricky due to Unicode and UTF-16 and all that).
When you subtract the character '0' from another character, you are essentially subtracting 48, the code point of the character DIGIT ZERO.
So, for example, something like '5' - '0' would evaluate to 53 - 48 = 5. You commonly see this pattern when "converting" strings containing digits to numeric values. It is not common to subtract '0' from a character like 'H' (whose codepoint is 72), but it is possible and Java does not care. It simply treats characters like integers.
http://www.ascii.cl/
'0' is 48 in ascii
'H' is 72.
Therefore 72-48 gives you 24

Why is my binary to decimal program giving incorrect outputs?

I'm working on this program that takes a binary string and converts it to decimal, using this guide to convert from binary to decimal. When I run through the for loop in my head, I get what the correct outputs would be. And yet, when I run my program, I get this strange output:
1
3
7
15
31
63
127
The actual output should look like this:
1
2
5
11
22
44
89
I cannot figure this out for the life of me. Why is my program doing this? Here's the current source code:
public class BinaryToDecimal
{
public static void main(String[] args)
{
String binary = "1011001";
int toMultiplyBy;
int decimalValue = 0;
for (int i = 1; i <= binary.length(); i++)
{
int whatNumber = binary.indexOf(i);
if (whatNumber == 0)
{
toMultiplyBy = 0;
}
else
{
toMultiplyBy = 1;
}
decimalValue = ((decimalValue * 2) + toMultiplyBy);
System.out.println(decimalValue);
}
}
}
Strings are 0 based so you should loop through the String from 0 to < the String's length, but indexOf(...), is not what you want to use since this will search for the location in the String of small ints which makes no sense. You don't care where the char equivalent of 2 is located in the String or even if it is in the String at all.
Instead you want to use charAt(...) or subString(...) and then parse to int. I would use
for (int i = 0; i < binary.length(); i++) {
int whatNumber = charAt(i) - '0'; // converts a numeric char into it's int
//...
To see what this is doing, create and run:
public class CheckChars {
public static void main(String[] args) {
String foo = "0123456789";
for (int i = 0; i < foo.length(); i++) {
char myChar = foo.charAt(i);
int actualIntHeld = (int) myChar;
int numberIWant = actualIntHeld - '0';
System.out.printf("'%s' - '0' is the same as %d - %d = %d%n",
myChar, actualIntHeld, (int)'0', numberIWant);
}
}
}
Which returns:
'0' - '0' is the same as 48 - 48 = 0
'1' - '0' is the same as 49 - 48 = 1
'2' - '0' is the same as 50 - 48 = 2
'3' - '0' is the same as 51 - 48 = 3
'4' - '0' is the same as 52 - 48 = 4
'5' - '0' is the same as 53 - 48 = 5
'6' - '0' is the same as 54 - 48 = 6
'7' - '0' is the same as 55 - 48 = 7
'8' - '0' is the same as 56 - 48 = 8
'9' - '0' is the same as 57 - 48 = 9
The numbers that represent the chars is based on the old ASCII table that gave each symbol a numeric representation. For more on this, please look here: ASCII Table
Two points:
Array indexing starts at zero, not 1, so your loop should be `for (int i=0; i
You are confusing indexOf() with substring(). In your case, binary.indexOf(i) does the following. First, the integer i is converted to a string. Then binary is searched left-to-right for a substring matching the string value of i. The first time through the loop i==1. This returns zero, because there's a 1 at index zero in binary. The second time, the value of i is 2. There's no 2 in binary, so this returns zero. For i==3, you're looking for a string 3 in binary, which will never be true.
Take a look at the String#substring() method, which is what I believe you intended.

Categories

Resources