Java: Subtract '0' from Char to Get an Int... Why Does This Work

Java: Subtract '0' from char to get an int... why does this work?

That's a clever trick. char's are actually of the same type / length as shorts. Now when you have a char that represents a ASCII/unicode digit (like '1'), and you subtract the smallest possible ASCII/unicode digit from it (e.g. '0'), then you'll be left with the digit's corresponding value (hence, 1)

Because char is the same as short (although, an unsigned short), you can safely cast it to an int. And the casting is always done automatically if arithmetics are involved

How does subtracting the character '0' from a char change it into an int?

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

String.chars() - why i - '0' is used here?

i - '0' is a common hack to convert an ASCII (or similar) digit's value into an actual number. For example, the encoding of '5' isn't actually 5 but some other value (53 or something in ASCII, I think). But the encoding of '5' is 5 larger than the encoding of '0' in most systems. So subtracting the value of '0' (the encoding for character '0') from the encoding of character '5' will yield a numerical value of 5.

Adding and subtracting chars, why does this work?

From the Docs

The char data type is a single 16-bit Unicode character.

A char is represented by its code point value:

  • min '\u0000' (or 0)
  • max: '\uffff' (or 65,535)

You can see all of the English alphabetic code points on an ASCII table.

Note that 0 == \u0000 and 65,535 == \uffff, as well as everything in between. They are corresponding values.

A char is actually just stored as a number (its code point value). We have syntax to represent characters like char c = 'A';, but it's equivalent to char c = 65; and 'A' == 65 is true.

So in your code, the chars are being represented by their decimal values to do arithmetic (whole numbers from 0 to 65,535).

For example, the char 'A' is represented by its code point 65 (decimal value in ASCII table):

System.out.print('A'); // prints A
System.out.print((int)('A')); // prints 65 because you casted it to an int

As a note, a short is a 16-bit signed integer, so even though a char is also 16-bits, the maximum integer value of a char (65,535) exceeds the maximum integer value of a short (32,767). Therefore, a cast to (short) from a char cannot always work. And the minimum integer value of a char is 0, whereas the minimum integer value of a short is -32,768.


For your code, let's say that the char was 'D'. Note that 'D' == 68 since its code point is 68.

return 10 + ch - 'A';

This returns 10 + 68 - 65, so it will return 13.

Now let's say the char was 'Q' == 81.

if (ch >= 'A' && ch <= 'F')

This is false since 'Q' > 'F' (81 > 70), so it would go into the else block and execute:

return ch - '0';

This returns 81 - 48 so it will return 33.

Your function returns an int type, but if it were to instead return a char or have the int casted to a char afterward, then the value 33 returned would represent the '!' character, since 33 is its code point value. Look up the character in ASCII table or Unicode table to verify that '!' == 33 (compare decimal values).

Why does subtracting '0' in C result in the number that the char is representing?

Because the char are all represented by a number and '0' is the first of them all.

On the table below you see that:

'0' => 48
'1' => 49

'9' => 57.

As a result: ('9' - '0') = (57 − 48) = 9

Sample Image
Source: http://www.asciitable.com

Java: What does subtracting a char by a char mean?

The goal is count the occurrences of each character.

c - 'a'

is a kind of clever way to get the position of the character in the alphabet. 'a' - 'a' would give you 0. 'b' - 'a' would give you 1. 'c' - 'a' would give you 2, and so on.

That value is used as an index into the array (which as you correctly stated is initialised with zeros) and the count is incremented.


It's worth noting that this will break if any character other than a-z is present in the string (including uppercase characters), and you'd see an IndexOutOfBoundsException

Why I should subtract '0' so that I can do int_arr[5] = char_string[5]?

The ASCII values for digits 0 - 9 are:

Digit          0   1   2   3   4   5   6   7   8   9

ASCII value 48 49 50 51 52 53 54 55 56 57

So if you have a string representation of an integer, say

char int_str[] = "123456";

and need to convert each char to its numeric value, subtracting the value for '0' (48) from each will will result in the values

int_str[0] == '1' ==>  '1' - '0' ==> 42 - 41 == 1
int_str[1] == '2' ==> '2' - '0' ==> 43 - 41 == 2
int_str[2] == '3' ==> '3' - '0' ==> 44 - 41 == 3
int_str[3] == '4' ==> '4' - '0' ==> 45 - 41 == 4
int_str[4] == '5' ==> '5' - '0' ==> 46 - 41 == 5
int_str[5] == '6' ==> '6' - '0' ==> 47 - 41 == 6

To get digits 1 2 3 4 5 6 into the integer 123456 requires additional steps:

This example uses the same conversions encapsulated into a function to convert discrete char digit to int digit values, then assimilate each discrete int digit value into the composite integer value:

int main(void)
{
char str[] = "123456";
int int_num = str2int(str);

return 0;
}

int str2int(char *str)
{
int sum=0;

while(*str != '\0')
{ //qualify string
if(*str < '0' || *str > '9')
{
printf("Unable to convert it into integer.\n");
return 0;
}
else
{ //assimilate digits into integer
sum = sum*10 + (*str - '0');
str++;
}
}
return sum;
}

How can I convert a char to int in Java?

The ASCII table is arranged so that the value of the character '9' is nine greater than the value of '0'; the value of the character '8' is eight greater than the value of '0'; and so on.

So you can get the int value of a decimal digit char by subtracting '0'.

char x = '9';
int y = x - '0'; // gives the int value 9

Subtracting '0' for converting String to int manually

The method .charAt(int position) returns a single character from your number string. Since your string contains a number you will receive a character which contains a digit (0 - 9). The next step would be to convert this character to an int.

a naive solution would be:

char digit = number.charAt(i);
if (digit == '0') {
num += 0;
} else if (digit == '1') {
num += 1;
}

But we can use the ASCII values of our characters to simplify this. Take a look at this ASCII table (only the columns 'Dec' and 'Chr'). You will see that the character 0 has in fact a value of 48. So if we substract 48 from our character we retrieve the correct value:

int num = digit - 48;

This can even be more simplified by directly placing the character which will be replaced by the compiler:

int num = digit - '0';

example:

character '4' has an ASCII value of 52. If we substract 48 we get 4 which is the wanted result.



Related Topics



Leave a reply



Submit