private int sumCharValues (String input) {
String total = input.toLowerCase();
int result = 0;
for (int i = 0, n = total.length(); i < n; i++) {
char c = total.charAt(i);
result += (c - 'a' + 1);
}
return result;
}
I'm trying to understand this code. What does the result += (c - 'a' + 1) means?
Any help would be very much appreciated.
It gives the letter's numerical position in the alphabet.
String total = input.toLowerCase(); means all the letters are lower case. Then, c - 'a' subtracts the ascii value for 'a' from the ascii value of c. That means you'll get anything from 0-25. Adding one shifts your starting point, giving you 1-26.
Try it in your head or add a print statement in your code for this expression.
When the character in the string is 'a', the expression reads 'a' - 'a' + 1 so you can see that the result will be 1.
When you're performing arithmetic on characters, you're actually doing it on their Unicode value,
For non-accented alphabetic characters, that is the same as ASCII value.
For 'a', this value is 97, for 'b', it's 98, etc.
So the expression above returns the index of the character in the alphabet, starting with 1 for 'a'.
The a += b operator is (more or less—see below) a shortcut for a = a + (b). The expression (c - 'a' + 1) converts the character stored in c to an integer in such a way that 'a' will have the value 1, 'b' will have the value 2, etc., based on the Unicode code points of the characters in input. When the loop exits, result will be the sum of all the numerical equivalents of the characters in the input.
The compound assignment a += b isn't exactly a shortcut for a = a + (b) in a couple of ways. First, the left side is evaluated only once, so something like vec[i++] += 3 will increment i only once. Second, there is an implicit cast (if necessary) to the type of a. Thus,
byte a = 0;
a += 1; // works
a = a + 1; // compiler error -- a + 1 is an int value
The statement result += (c - 'a' + 1) is evaluated as,
First char c is converted to its ASCII value, then we get the diff between ascii value of char c and char 'a' and then we add 1 to it.
And this statement result += (c - 'a' + 1) can be rewritten as result = result + (c - 'a' + 1), i.e. we are just adding the previous value of result and assigning it again.
PS: The ASCII value of 'a' is 97 and 'z' is 122.
For e.g. if input String is "stackoverflow", it will be evaluated as,
char c = 's', result = 19
char c = 't', result = 39
char c = 'a', result = 40
char c = 'c', result = 43
char c = 'k', result = 54
char c = 'o', result = 69
char c = 'v', result = 91
char c = 'e', result = 96
char c = 'r', result = 114
char c = 'f', result = 120
char c = 'l', result = 132
char c = 'o', result = 147
char c = 'w', result = 170
Related
For case #1, adding 2 to 'a' gives us 'c'.
How can I write a program so that adding 2 to 'z' gives 'b' as an output and subtracting 3 from 'a' gives 'x' as an output?
In other words, I want only alphabet character as an output. No matter how big number you are adding or subtracting to and from the character, I always expect the output between a and z inclusive.
case #1
public void addNumberToCharacter{
char character = 'a' + 2;
System.out.println(character); // 'c'
}
case #2
public void addNumberToCharacter{
char character = 'z' + 2;
System.out.println(character); // 'b'
}
case #3
public void addNumberToCharacter{
char character = 'a' - 3;
System.out.println(character); // 'x'
}
To handle two cases you might also require:
uppercase and lowercase;
adding/subtracting number whose absolute value is bigger than 26;
And here is the method you can refer to:
private static void addNumToChar(int a, char c0) {
char c = 'a';
if(Character.isUpperCase(c0)) {
c = 'A';
}
while (a < 0) a += 26;
char c1 = (char) (c + (c0 - c + a) % 26);
System.out.println(c1);
}
Run the test as follows:
addNumToChar(2, 'B'); // D
addNumToChar(2, 'b'); // d
addNumToChar(261, 'B'); // C
addNumToChar(261, 'b'); // c
addNumToChar(-2, 'B'); // Z
addNumToChar(-2, 'b'); // z
addNumToChar(-261, 'B'); // A
addNumToChar(-261, 'b'); // a
After you add or subtract, correct with:
character = (character + 26 - 'a')%26 + 'a';
Java's x%y operator gives the remainder from integer division of x by y. Subtracting 'a' gives the offset from the start of the lowercase alphabet, and then adding 26 guarantees a positive sum, provided you didn't add an offset less than -26 or subtract more than +26.
public char number(int num, char c){ // -- num =29, char= 'd'
int n = c - 96 ; // n = 4
n = n+(num%26); // n = 4 + 3 = 7
if(n > 26){ return (char)(n-26); } // doesnot follow
else if(n < 0){ return (char)(n+26); } // doesnot follow
else { return (char)(n); } // return g
}
You can try this method. It can handle positive as well as negative number.
use that one :-
public static void main(String[] args) {
char c= 'a' - 1;
if(!(c>=97 && c<=122)) {
if(c>=123)
c= (char) (c-26);
else
c= (char) (c+26);
}
System.out.println(c);
}
I am trying to reform a string from ascii characters. I noticed when I break down ascii it matches the number with the ascii char, this changes when I tried to do (c+=c+0) on it as seen below, I tried to revert back to the original string but it doesn't seems to work. I was wondering does the ascii number change when you append it to a string?
StringBuilder b = new StringBuilder();
char c = "e".charAt(0);
System.out.println(c); //'e'
System.out.println(c+0); //101 -ascii
b.append(c+=c+0);
char d = b.charAt(0);
System.out.println(d-=d+0); //blank
When you use + to sum a char with and int, the result will be promoted
to int.
When you use compound assignment operators +=, the result will be converted to left
operand data type(in this case, char)
This is what happens with your code:
StringBuilder b = new StringBuilder();
char c = "e".charAt(0);
System.out.println(c); //'e'
System.out.println(c+0); //101 -ascii
b.append(c+=c+0); // result of c+c+0 is int 202, it is converted to char Ê
char d = b.charAt(0); // char d = Ê
System.out.println(d-=d+0); // result of d-(d+0) is int 0, it will be converted to null
It's not clear what you're trying to accomplish, but hopefully this example helps you figure out what's going on:
public static void main(String[] args) {
StringBuilder b = new StringBuilder();
char c = "e".charAt(0);
System.out.println(c); // e
System.out.println((int) c); // 101
char doubleC = (char) (c + c);
b.append(doubleC);
char d = b.charAt(0);
System.out.println((int) d); // 202
System.out.println(d - c); // 101
System.out.println((char) (d - c)); // e
}
Whether a character is printed as a letter or its ASCII value depends on its type. You can see that (int) c casts the character to its int ASCII value. Your approach of c+0 also does this but in a less intuitive way.
You also apparently want to "undo" your modification to c, but subtracting d-d always gives you 0. You need to store your value of c and subtract that from d.
+0s don't do anything because the character is underneath a number (so it's essentially like saying 101 + 0).
d-=d+0 evaluates to d = d - d + 0, so (because we're manipulating chars) d - d = 0
If you wanted to get c from d, you'd have to do d = d - c, because 'c' is the difference between the initial and the final value.
So no, the ASCII number of a character doesn't change, you're just not doing the reverse calculation as you should be.
It's like saying: x + y = z,
and then wondering why z - z != y.
You should be doing: z - x = y
#Edit
To add to your comment under pkpnd's answer - if you have only String b to work with, you'd still need to know the difference (i.e. by how much you increased/decreased the number) to reverse to the original chars.
I found an exercise to convert from hex to decimal using casting, but I did not understand how that decimal + 'A' - 10 worked. Can anybody explain me?
code is here:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a decimal value (0-15):");
int decimal = input.nextInt();
if (decimal <= 9 && decimal >= 0) {
System.out.println("The hex value is: " + decimal);
}
else if (decimal >= 10 && decimal <= 15) {
System.out.println("The hex value is " + (char)(decimal + 'A' - 10));
}
else {
System.out.println("It's an invalid input.");
}
}
}
Thanks.
The alphabetical characters in Unicode have sequential codes:
A = 65
B = 66
C = 67
D = 68
...
So, the value of (char)('A'+1) is the same as 'B', as the char value 'A' is interpreted as 65 when used in an arithmetic expression, and then the +1 makes it 66, and then you cast it as char again, it's 'B'.
So what you have there is the value of 'A' plus the difference between the decimal and 10 (which is 0 through 5). This will give you the values 'A' + 0, 'A' + 1, 'A' + 2 etc, which means 'A', 'B', 'C' respectively when you calculate it.
Each char has integer value associated with it. Hence casting int to (char) will yield to char value.
How do I get the numerical value/position of a character in the alphabet (1-26) in constant time (O(1)) without using any built in method or function and without caring about the case of the character?
If your compiler supports binary literals you can use
int value = 0b00011111 & character;
If it does not, you can use 31 instead of 0b00011111 since they are equivalent.
int value = 31 & character;
or if you want to use hex
int value = 0x1F & character;
or in octal
int value = 037 & character;
You can use any way to represent the value 31.
This works because in ASCII, undercase values are prefixed with 011, and uppercase 010 and then the binary equivalent of 1-26.
By using the bitmask of 00011111 and the AND operand, we covert the 3 most significant bits to zeros. This leaves us with 00001 to 11010, 1 to 26.
Adding to the very good (self) answer of Charles Staal.
Assuming ascii encoding following will work. Updated from the kind comment of Yves Daoust
int Get1BasedIndex(char ch) {
return ( ch | ('a' ^ 'A') ) - 'a' + 1;
}
This will make the character uppercase and change the index.
However a more readable solution (O(1)) is:
int Get1BasedIndex(char ch) {
return ('a' <= ch && ch <= 'z') ? ch - 'a' + 1 : ch - 'A' + 1;
}
One more solution that is constant time but requires some extra memory is:
static int cha[256];
static void init() {
int code = -1;
fill_n (&cha[0], &cha[256], code);
code = 1;
for(char s = 'a', l = 'A'; s <= 'z'; ++s, ++l) {
cha[s] = cha[l] = code++;
}
}
int Get1BasedIndex(char ch) {
return cha[ch];
}
We can get their ASCII values and then subtract from the starting character ASCII(a - 97, A - 65)
char ch = 'a';
if(ch >=65 && ch <= 90)//if capital letter
System.out.println((int)ch - 65);
else if(ch >=97 && ch <= 122)//if small letters
System.out.println((int)ch - 97);
Strictly speaking it is not possible to do it portably in C/C++ because there is no guarantee on the ordering of the characters.
This said, with a contiguous sequence, Char - 'a' and Char - 'A' obviously give you the position of a lowercase or uppercase letter, and you could write
Ord= 'a' <= Char && Char <= 'z' ? Char - 'a' :
('A' <= Char && Char <= 'Z' ? Char - 'A' : -1);
If you want to favor efficiency over safety, exploit the binary representation of ASCII codes and use the branchless
#define ToUpper(Char) (Char | 0x20)
Ord= ToUpper(Char) - 'a';
(the output for non-letter character is considered unspecified).
Contrary to the specs, these snippets return the position in range [0, 25], more natural with zero-based indexing languages.
char c = '0';
int i = 0;
System.out.println(c == i);
Why does this always returns false?
Although this question is very unclear, I am pretty sure the poster wants to know why this prints false:
char c = '0';
int i = 0;
System.out.println(c == i);
The answer is because every printable character is assigned a unique code number, and that's the value that a char has when treated as an int. The code number for the character 0 is decimal 48, and obviously 48 is not equal to 0.
Why aren't the character codes for the digits equal to the digits themselves? Mostly because the first few codes, especially 0, are too special to be used for such a mundane purpose.
The char c = '0' has the ascii code 48. This number is compared to s, not '0'. If you want to compare c with s you can either do:
if(c == s) // compare ascii code of c with s
This will be true if c = '0' and s = 48.
or
if(c == s + '0') // compare the digit represented by c
// with the digit represented by s
This will be true if c = '0' and s = 0.
The char and int value can not we directly compare we need to apply casting. So need to casting char to string and after string will pars into integer
char c='0';
int i=0;
Answer is like
String c = String.valueOf(c);
System.out.println(Integer.parseInt(c) == i)
It will return true;
Hope it will help you
Thanks
You're saying that s is an Integer and c (from what I see) is a Char.. so there you, that's the problem: Integer vs. Char comparation.