I have a question about the following snippet:
while (str.length() > i && str.charAt(i) >= '0' && str.charAt(i) <= '9') {
result = result * 10 + (str.charAt(i) - '0');
i++;
}
Could someone tell me why str.charAt(i) - '0' is considered and what does it do?
Also, why is the result multiplied by 10?
Thanks!
By doing Str.CharAt(i) -'0' you just convert the caracter to the real number value provided that character is in 0 .. 9 range.
The result = result * 10 thing is to "shift" previous result to the left (decimal base), since a new digit has been detected (and added to the result)
This code is probably doing a string to integer conversion, also a bad one since it seems that 12AAA34 would be converted to 1234 since non-digit charts are just skipped. It would be better if parsing stopped as soon as a non-digit char was found, like C atoi does (still accepting/skipping spaces)
First of all this Str.CharAt(i) - '0' is considered because both Str.CharAt(i) and '0' returns Characters which have their ascii values to be integers.
It means that taking the value of the String Str fetch the character at index number i of the String(Str). For example consider this String Emil.
Then "Emil".CharAt(0); will give me E. But E has an ascii value of 69 which is an integer. Also 0 has an ascii value of 48. So "Emil".CharAt(0); - 0 is equivalent to 69 - 48(thus the subtraction of two integer values) and returns and integer of 21.
It(Str.CharAt(i) - 0) is added to the results of results * 10 because Str.CharAt(i) - 0 returns a Character which can also be recognise as an Integer(ascii) in java.
Take a look at this stackoverflow page which also have an ascii to character table to make you understand more.
Related
I've been trying to do this simple program where I need to check which digit of an integer number is the biggest one. So my initial thought was that I shall convert it all into an array and go with the for loop to check which element of an array is biggest. In order to do this I converted integer into String and then characters of the String into elements of an array. I ran into problem and I looked online for solution. What I don't understand is why do I need the " temp.charAt(i) - '0'" part in order to store characters of String as elements of the array. Why can't it be only arrTemp[i] = temp.charAt(i), without the "- '0'" part.
String temp = Integer.toString(n);
int arrTemp[] = new int[temp.length()];
int max = arrTemp[0];
for(int i = 0; i<temp.length(); i++) {
arrTemp[i] = temp.charAt(i) - '0';
'0' is the character '0', not the integer 0. Characters are represented using int values (ascii code).
The ascii code for '0' is the integer value 48.
int n = (int) '0'; //n would be 48.
So, to convert '0' to the integer 0, you need to subtract '0'-'0' = 48-48 = 0
To convert '9' to int 9:
'9' - '0' = 57-48 = 9
See ASCII code https://en.wikipedia.org/wiki/ASCII
In many programming languages(Java, C etc.), a character variable does not contain a character value itself rather the ascii value of the character variable. The ascii value represents the character variable in numbers, and each character variable is assigned with some number range from 0 to 127(in decimal number system). For example, the ascii value of 'A' is 65 and '0' is 48.
You can convert any digit character to integer by subtracting '0' from that character. This subtraction between characters is possible because of ascii values.
Imagine you want to convert digit character '9' to an integer 9. ASCII value of character '9' is 57 and ASCII value of character '0' is 48. Now, if you perform a subtraction operation of characters, '9' - '0', it will be treated like 57 - 48 and thus will give you a result of 9. This subtraction operation of characters converted a character '9' to an Integer 9.
Try this code example:
class Converter {
public static void main(String[] args) {
System.out.println('9'-'0');
}
}
You can see all of the characters points to an ascii value,
I am new to java and and working on a crud calculator that takes input and holds it in an ArrayList to perform the calculations.
I am trying to add two values in an ArrayList<Character> and then replace the "+" with the sum.
if(listEqu.contains('+')) {
while(listEqu.indexOf('+') > -1) {
int plus = listEqu.indexOf('+');
int prev = listEqu.get(plus-1);
int nxt = listEqu.get(plus+1);
Character sum = (char) (nxt + prev);
listEqu.set(plus, sum);
System.out.println(listEqu);
}
}
When the input is 1+1, this returns [1, b, 1].
What I want is to return [1, 2, 1] .
Any advice? Thanks!
The problem is actually that adding two characters doesn't do what you expect.
The value of '1' + '1' is 'b'. If you want the next digit after '1' you add the integer 1 to it; i.e. '1' + 1 is '2'.
For a deeper understanding, you need to understand how character data is represented in Java.
Each char value in Java is an unsigned 16 bit integer that corresponds to a code point (or character code) in the Unicode basic plane. The first 128 of these code points (0 to 127) correspond to a characters in the old ASCII character set. In ASCII the codes that represent digits are 48 (for '0') through to 39 (for '9'). And the lowercase letters are 97 (for 'a') through to 122 (for 'z').
So as you can see, '1' + '1' -> 49 + 49 -> 98 -> 'b'.
(In fact there is a lot more to it than this. Not all char values represent real characters, and some Unicode code-points require two char values. But this is way beyond the scope of your question.)
How could I specify addition of numbers instead of addition of the characters?
You convert the character (digit) to a number, perform the arithmetic, and convert the result back to a character.
Read the javadoc for the Character class; e.g. the methods Character.digit and Character.forDigit.
Note that this only works while the numbers remain in the range 0 through 9. For a number outside of that range, the character representation consists of two or more characters. For those you should be using String rather than char. (A String also copes with the 1 digit case too ...)
Few things that can be improved with your code :
Converting the characters 1 into equivalent integer value:
int prev = Integer.parseInt(String.valueOf(listEqu.get(plus-1)));
int nxt = Integer.parseInt(String.valueOf(listEqu.get(plus+1)));
// Note : int prev = listEqu.get(plus-1) would store an ascii value of `1` to prev value i.e 49
And then converting the sum of those two values into Character back to be added to the list using Character.forDigit as:
Character sum = Character.forDigit(nxt+prev,10);
// Note Character sum = (char) (nxt + prev); is inconvertible
// and char sum = (char) (nxt + prev); would store character with ascii value 98(49+49) in your case 'b' to sum
you should first convert your prevand nxt to int value and then add them together like follow:
if(listEqu.contains('+')) {
while(listEqu.indexOf('+') > -1) {
int plus = listEqu.indexOf('+');
int prev = Integer.parseInt(listEqu.get(plus-1));
int nxt = Integer.parseInt(listEqu.get(plus+1));
Character sum = (char) (nxt + prev);
listEqu.set(plus, sum);
System.out.println(listEqu);
}
}
nxt and prev are char values. Tey take their value in the ASCII table, where '1' is 61 and 'b' is 142 (thus, '1' + '1' = 'b')
You need to substract '0' to get the number they represent. ('1' - '0' = 61 - 60 = 1)
The sum is not necessarily writable with one character, so you shouldn't put it back into a char array.
If you want to convert an integer to a string, use Integer.toString(i).
(And, if you want to, get the first character of the string and put it in the array, if that's what you want)
You need to parse the characters to their corresponding decimal value before you perform the addition, and then back to a character after. The methods Character.digit(char, int) and Character.forDigit(int, int) can do that (and I would use char since that is the type of prev and nxt). Like,
char prev = listEqu.get(plus - 1);
char nxt = listEqu.get(plus + 1);
Character sum = Character.forDigit(Character.digit(nxt, 10)
+ Character.digit(prev, 10), 10);
int x=(int)compressedText.charAt(one1+1);
int y=(int)compressedText.charAt(one1+2);
count=x+y;
count1=(char)count;
the craracter value for compressedText.charAt(one1+2) and compressedText.charAt(one1+1) are each equal to 1 but when I try to debug my code it says count is equal to 98.
Casting a char that represents a numeric character to an int doesn't do what you think it does. It takes the Unicode value of the char (which is 49 for '1'). That explains why you get 98 instead of 2.
Because the code values for the characters '0' through '9' are 48 through 57, you can subtract '0' (48) from each char instead, e.g.
int x = compressedText.charAt(one1+1) - '0';
You'll need to undo this conversion if you are converting an int back to a char that is meant to represent the numeric character. Also you'll need to account for multiple characters if count is more than one digit (>= 10).
This method works in C, C++ and Java. I would like to know the science behind it.
The value of a char can be 0-255, where the different characters are mapped to one of these values. The numeric digits are also stored in order '0' through '9', but they're also not typically stored as the first ten char values. That is, the character '0' doesn't have an ASCII value of 0. The char value of 0 is almost always the \0 null character.
Without knowing anything else about ASCII, it's pretty straightforward how subtracting a '0' character from any other numeric character will result in the char value of the original character.
So, it's simple math:
'0' - '0' = 0 // Char value of character 0 minus char value of character 0
// In ASCII, that is equivalent to this:
48 - 48 = 0 // '0' has a value of 48 on ASCII chart
So, similarly, I can do integer math with any of the char numberics...
(('3' - '0') + ('5' - '0') - ('2' - '0')) + '0') = '6'
The difference between 3, 5, or 2 and 0 on the ASCII chart is exactly equal to the face value we typically think of when we see that numeric digit. Subtracting the char '0' from each, adding them together, and then adding a '0' back at the end will give us the char value that represent the char that would be the result of doing that simple math.
The code snippet above emulates 3 + 5 - 2, but in ASCII, it's actually doing this:
((51 - 48) + (53 - 48) - (50 - 48)) + 48) = 54
Because on the ASCII chart:
0 = 48
2 = 50
3 = 51
5 = 53
6 = 54
In C the + and - operators apply integer promotion*1 to their arguments, thus the result of subtracting (or adding) two chars is an int*2.
From the C-Standard:
5.1.2.3 Program execution
[...]
10 EXAMPLE 2 In executing the fragment
char c1, c2;
/* ... */
c1 = c1 + c2;
the ‘‘integer promotions’’ require that the abstract machine promote the value of each variable to int size and then add the two ints [...]
Applying this to the OP's implicitly given use case of
char c = 42;
... = c - `0`;
This would be lead to the above being the same as:
... = (int) c - (int) `0`; /* The second cast is redundant, as per Jens' comment. */
^ ^
+------ int -----+
*1: If the operators arguments have a lower rank than int they are promoted to an int.
*2: char has a lower rank than int.
There's no change going on. '0' is an int in C. It is a fancy way to write 48 (assuming ASCII).
You can convince yourself of this fact by computing the size of '0':
printf ("sizeof '0' is %zu\n", sizeof '0');
printf ("sizeof(char) is %zu\n", sizeof(char));
which in the first line very likely prints 4 (or 2) but probably not 1 like in the second row (again: in C; it's different for C++).
The numeric constant 0, without any qualifications, has type int. The result of the binary subtraction operation on a char and an int also has type int due to the usual type promotion process.
This question already has answers here:
Explain the use of a bit vector for determining if all characters are unique
(12 answers)
Closed 8 years ago.
I have a program which I found online which basically tells whether the String contains all unique characters, below is the code
private static boolean areCharsUnique(String str) {
if (str.length() > 256)
return false;
int checker = 0;
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) - 'a';
if ((checker & (1 << val)) > 0) {
return false;
}
checker |= (1 << val);
}
return true;
}
I am baffled by this line of code if ((checker & (1 << val)) > 0) and also
checker |= (1 << val);
I know that << is a left shift operator, but how exactly left shifting helps in the above situation?
In short how does the above program work?
This code works under the assumption that ASCII character set has consecutive character in its mapping so that a == 97, b == 98, and so on.
Starting from this you can calculate a delta distance from the a character, eg 'e' - 'a' = 5. This distance is used to set (through checker |= (1 << val)) a bit in a integer number (which has 32 bits).
So if a 'e' character is found then bit at index 5 is set to 1 for checker.
This is done for every char by ensuring that you never find a bit that has been already set previously (through if (checker & (1 << val)) > 0)).
This works only for lowercase characters (even because int has 32 bits). An HashSet<Character> would be surely better.
Each character is converted to a numeric index from 0 (== 'a') to 26 (== 'z') and beyond. For each of those indexes, the corresponding bit in an integer value (== 'checker') is set. If the bit for that index is already set, you can determine that that character already was contained in the given string.
Note that this algorithm only works for lowercase strings, as for the uppercase characters, the value will overflow and give unreliable results. One fix for this would be to convert the 'checker' type from int to long.
We convert each character to a numeric index from 0 ('a') to 25 ('z') here
int val = str.charAt(i) - 'a';
Here we look at binary presentation of checker
for example, if checker = 001
this means we already have char 'a' counted, because first bit is set to 1.
In this row we check if bit related to current letter is set. 1<<val represent 00100..00, where 1 is set in val-th position from left. Others digits are zeros. About binary operation you may read at TopCoder
if ((checker & (1 << val)) > 0) {...}
This line checker |= (1 << val); set bit at position val from left to 1 in checker.
EDIT:
Here you may assume checker like bool arr[32],
and
int val = str.charAt(i) - 'a'; the same as if(arr[str.charAt(i) - 'a'] == true) ...
and
checker |= (1 << val); is equal to arr[val] = true.
So, at begging you have all elements of arr set to zeros.
val - is integer representation of letters from 'a' to 'z'.
This code store the presence of each lowercase character as a single bit in a 32-bit integer.
1 << val computes a number with only that bit set.