51

This works fine:

int foo = bar.charAt(1) - '0';

Yet this doesn't - because bar.charAt(x) returns a char:

int foo = bar.charAt(1);

It seems that subtracting '0' from the char is casting it to an integer.

Why, or how, does subtracting the string '0' (or is it a char?) convert another char in to an integer?

asked Nov 30, 2010 at 20:31
4
  • 36
    Don't make the mistake of thinking that '0' == 0. In reality, '0' == 48. Commented Nov 30, 2010 at 20:42
  • 2
    click Ah, now it makes perfect sense! If only you'd put that as an answer and pointed me to cs.utk.edu/~pham/ascii_table.jpg Commented Nov 30, 2010 at 20:57
  • this implicit cast doesn't return the decimal representation of the char, as @MarkPeters pointed, so if for example bar.charAt(1) returns 'A', which dec representation is 65, int foo will be 17, 'A' - '0' = 65 - 48 = 17 and not 65. Commented Sep 21, 2014 at 18:04
  • 1
    This trick is being used in a lot of questions in Leetcode, but I don't see anyone asked about how this trick works for Leetcode questions. Commented May 5, 2017 at 2:31

10 Answers 10

48

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

answered Nov 30, 2010 at 20:34

4 Comments

shorts can have negative values, char doesn't. Also is not ASCII but unicode ( small but important difference ) : try int y = '\uffff' - '\ufffe';
You're right. For digits, ASCII and Unicode codes happen to coincide, that's why I thought of ASCII first
That's great. I did need Mark Peter's comment to make me realise that by 'corresponding value' you mean I'm actually subtracting 48 from 49-57. Also, the error I was getting was really an array out of bounds exception so perhaps my question's misleading in saying the first example "doesn't work". Thanks! :)
To be clear, a char isn't considered a subtype of short in Java... your answer kind of makes it sound like it is. char and short are both direct subtypes of int. Also, "casting" is done automatically between any type and any type that is considered a supertype of it regardless of whether arithmetic is involved.
17

This is an old ASCII trick which will work for any encoding that lines the digits '0' through '9' sequentially starting at '0'. In Ascii, '0' is a character with value 0x30 and '9' is 0x39. Basically, if you have a character that is a digit, subtracting '0' "converts" it to it's digit value.

I have to disagree with @Lukas Eder and suggest that it is a terrible trick; because the intent of this action aproaches 0% obvious from code. If you are using Java and have a String that contains digits and you want to convert said String to an int I suggest that you use Integer.parseInt(yourString);.

This technique has the benifit of being obvious to the future maintenance programmer.

answered Nov 30, 2010 at 21:01

1 Comment

it's a clever trick. and clever is always a bad thing. it's the opposite of elegant :-)
3

'0' is a char too. It turns out, the characters in Java have a unicode (UTF-16) value. When you use the - operator with characters Java performs the operation with the integer values.

For instance, int x = 'A' - '0';// x = 17

answered Nov 30, 2010 at 20:40

5 Comments

It doesn't complain at all. You can do int y = s.charAt(1) just fine, without compile or runtime error (assuming s has two+ characters). I think the OP was confused as to why it didn't return the same result.
@Bart: UTF-16 is an encoding format for unicode, but yes you're right.
@Mark: I know, but for characters above unicode point 65k, (at least) two UTF-16 char's are used
You chose a great example to illustrate to limited usefulness of character arithmetic.
With above example , I get jshell> int x = '0' - 'A' x ==> -17.
1

chars are converted to int implicitly:

 public static void main(String [] args) throws Exception {
 String bar = "abc";
 int foo = bar.charAt(1) - '0';
 int foob = bar.charAt(1);
 System.err.println("foo = " + foo + " foob = " + foob);
 }

output: foo = 50 foob = 98.

Maybe you put two int foo ... and this is because it didn't work?

answered Nov 30, 2010 at 20:39

Comments

1

The following code works perfectly fine!

int foo = bar.charAt(1);

Similar to reference types, any Java primitive can be assigned without casting to another primitive of a type it is considered a subtype of. The subtyping rules for primitives are given by JLS section 4.10.1. char is considered a subtype of int, so any char may be assigned to an int.

answered Nov 30, 2010 at 20:42

1 Comment

Are you sure? String s = "9"; int n = s.charAt(0); System.out.println(n); returns 57
1

Your code may compile without error & run without throwing an exception, but converting between char's & int's is bad practice. First, it makes the code confusing, leading to maintenance headaches down the road. Second, clever "tricks" can prevent compilers from optimizing the byte code. One of the best ways to get fast code is to write dumb code (i.e., not clever code).

answered Dec 1, 2010 at 15:58

Comments

0

Because in Java if you do not specify a type indicator with a number then it assumes Integer. What I mean by that, if you want to set a Long value, it would need to be 0L.

Performing a numerical operation on two different numerics, the result takes the larger. Hence, a char (which is a numerical value) minus an integer, results in an integer.

You will find that this works also

long val = bar.charAt(1) - 0L;
answered Nov 30, 2010 at 20:34

1 Comment

@Lukas it won't, see my answer.
0

Your second snipped should work fine though:

int foo = bar.charAt(1);

A char, just like a short or byte, will always be silently cast to int if needed.

This will compile just fine: int i = 'c';

answered Nov 30, 2010 at 20:40

2 Comments

Not saying it is, just that you don't need to explicitly cast char to int, so it's not clear why searbe would need the subtraction.
nah, if i have a "char c=bar.charAt(1); //c=1;" then "int foo=c;" foo will be 49 not 1. . So subtracting "int foo=c-'0'; returns 1. :) because 49-48=1
0

I will echo what @Mark Peters has said above in case people overlook his comment.

As I quote: " Don't make the mistake of thinking that '0' == 0. In reality, '0' == 48 "

answered Aug 29, 2020 at 4:20

Comments

0

'5' has the int value of 53

if we write '5'-'0' it evaluates to 53-48, or the int 5

if we write char c = 'B'+32; then c stores 'b'

'b' = 98.

Please refer ASCII chart https://en.cppreference.com/w/cpp/language/ascii

answered Feb 8, 2022 at 1:52

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.