Java hashCode method maximum return value - java

Can someone tell me what are the maximum and minimum int values that the Java String.hashCode() method can return?

String.hashCode () return an int calculated by using the below formula:
public int hashCode()
Returns a hash code for this string.
The hash code for a String object is computed as
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
using int arithmetic, where s[i] is the i-th character of the string, n is the length of the string, and ^ indicates
exponentiation. (The hash value of the empty string is zero.)
The minimum and max value can be found with the below constants.
System.out.println (java.lang.Integer.MAX_VALUE); // 2147483647
System.out.println (java.lang.Integer.MIN_VALUE); // -2147483648

Java int is 4 bytes, signed (two's complement). -2,147,483,648 to 2,147,483,647. Like all numeric types ints may be cast into other numeric types (byte, short, long, float, double). When lossy casts are done (e.g. int to byte) the conversion is done modulo the length of the smaller type.

From the documentation, given that the power to which something is raised depends on the length of the String (which is practically unlimited, as far as I know), I would say that the maximum and minimum must be Integer.MAX_VALUE (2^31 - 1) and Integer.MIN_VALUE (-2^31), respectively.

Related

Why byte casting returns decimal value of char?

I have Python background and I don't understand that how byte casting returns decimal value of char according to ASCII.
Here are the some code examples:
// C#
string s = "abc123éé";
int[] x = new int[255];
for (int i = 0; i < s.Length; i++){
amount[(byte)s[i] - (byte)'0']++;
}
If we look for first iteration the casting is on 'a' char and it returns 97.
// Java
char a = 'a';
System.out.println((byte)a);
Same as Java, it returns 97 too. But in Python 3, it does not return as decimal value of char.
>>> a = bytes("a", encoding="utf-8")
>>> a
b'a'
And now if we're coming to my questions:
How / Why byte casting works like this?
I know that byte's value range is -128 to 127 but char's is 0 to 255. How does not it give an exception even 'é' value is 233?
What's the difference between Python at this point?
Only for Java, I do not use Python:
How / Why byte casting works like this?
It is specified by the Java Language Specification, mostly JLS-5.1.3: "...A narrowing conversion of a char to an integral type T likewise simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the resulting value to be a negative number, even though chars represent 16-bit unsigned integer values..."
("Why?" because it is so specified)
I know that byte's value range is -128 to 127 but char's is 0 to 255. How does not it give an exception even 'é' value is 233?
Wrong, chars are 0 to 65535 (or '\u0000' to '\uFFFF') JLS-4.2.1
No reason for Exception, it will result in the byte value -23 (same bits as 'é' or int 233)
I must pass the last point/question, I do not know enough Python

Java : Need to get the same functionality of the Integer.toHexString() with a String parameter and not an Int parameter due to NumberFormat Exception

I have this line of Java code that will throw NumberFormatException if the number represented as a String is above 2,147,483,647.
Because:
The int data type is a 32-bit signed two's complement integer. It has
a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647
Code Throwing the NumberFormatException:
String largeNumberAsAString = "9999999999";
Integer.toHexString(Integer.parseInt(largeNumberAsAString)); // NumberFormatException
How can I get the same functionality of theInteger.toHexString() with a String parameter and not an int parameter due to NumberFormatException?
Use BigInteger to avoid numeric limits of primitive int and long:
BigInteger x = new BigInteger("9999999999999999999999"); // Default radix is 10
String x16 = x.toString(16); // Radix 16 indicates hex
System.out.println(x16);
The class conveniently exposes a constructor that takes a String, which gets interpreted as a decimal representation of a number.
Demo.
If your input value can be arbitrarily large, then #dasblinkenlight's answer involving BigInteger is your best bet.
However, if your value is less than 263, then you can just use Long instead of Integer:
String dec = "9999999999";
String hex = Long.toHexString(Long.parseLong(dec));
System.out.println(hex); // 2540be3ff
Live demo.
Use Integer.parseUnsignedInt
When the number is above 2^31 but below 2^32, thus in the negative int range,
you can do:
int n = Integer.parseUnsignedInt("CAFEBABE", 16);
(I used hexadecimal here, as it is easier to see that above we are just in that range.)
However 9_999_999_999 is above the unsigned int range too.
Try this way:
String largeNumberAsAString = "9999999999";
System.out.println(Integer.toHexString(BigDecimal.valueOf(Double.valueOf(largeNumberAsAString)).intValue()));

Integer in parentheses not compiling - Why?

I'm initializing two integers a and b.
It compiles fine for a but there is an error for b.
public class Main_1 {
public static void main(String[] args) {
int a = -2147483648; //Working fine
int b = -(2147483648); //Compilation error: The literal 2147483648 of type int is out of range
}
}
Please help me understand this behavior ?
The reason is that the int datatype has valid values in the range [-2147483648, 2147483647].
When you wrap 2147483648 inside parentheses, it becomes an expression that will be evaluated as an int. However, 2147483648 is too big to fit in an int (too big by one).
The problem does not happen for -2147483648 because it is a valid int value.
Relevant parts of the JLS:
adding parentheses creates a "Parenthesized Expressions" (section 15.8.5)
an integer literal, such as 2147483648, is treated as an int by default (section 3.10.1)
An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).
int values go from -2147483648 to 2147483647. So -(2147483648) is OutOfRange because the value inside the brackets is evaluated as an int. The max value you can put into the brackets is
Integer.MAX_VALUE //Which is equals to 2147483647
The compilation error is pretty clear: you are using the int literal which is out of range. If you really want to do it, you may use long literal:
int b = (int) -(2147483648L);
Or double literal:
int b = (int) -(2147483648.0);
Max value of int is 2147483647 and min value of int is -2147483648. But when you put 2147483648 into braces it initially consider as +2147483648 and it is not in valid for int rage.
A good way to visualize this is to look at (int) -(2147483648) as:
(int) -1 * (2147483648)
When this is evaluated by the compiler, it says, I have to first convert the number in the parenthesis to an integer, then multiply that by negative 1. It then proceeds to do a range check on the number and discovers that it is larger than what can fit in an integer (2147483648), which is the compilation error.
int data type is a 32-bit signed two's complement integer.
Minimum value is - 2,147,483,648.(-2^31)
Maximum value is 2,147,483,647(inclusive).(2^31 -1)

compile error, too large integer. CreditCardAnalysis.Java

I'm struggling to figure out what the compile/syntax error is in my code.
public class CreditCardValidation {
public static void main (String[] args){
System.out.print(prefixMatched(4388576018402626, 4388));
}
/*
Return the number of digits in d
*/
public static int getSize(long d) {
int size = 0 ;
while( d > 0 ) {
d = d / 10 ;
size = size + 1 ;
}
return size ;
}
/*
Return the first k number of digits from number. If the number of digits in number is
less than k, return the number.
*/
public static long getPrefix(long n, int k) {
int f = getSize(n)-k;
long prefix = n/((int)(Math.pow(10, f)));
return prefix;
}
/*
Return true if the digit d is a prefix for number.
*/
public static boolean prefixMatched( long number, int d ) {
if ( d == getPrefix(number, 4))
return true ;
else
return false ;
}
}
As you can see I'm trying to call prefixMatched to check whether the credit card number meets the requiremen; if digit d is a prefix for number. However, the only thing I get back from the compiler is:
"CreditCardValidation.java:6: integer number too large: 4388576018402626
System.out.print(prefixMatched(4388576018402626, 4388));
^"
I'm sorry if my question is too vauge, this is my first post.
You need to indicate to the compiler that your constant (the CC number) is a long. Put an L on the end of the constant.
It's actually a little easier to treat CC numbers as strings and use charAt(x) to calculate check digits.
The problem is that you are specifying an integer literal 4388576018402626 and that number is larger than the maximum integer, 2147483647.
You are attempting to pass it to a method that takes a long, so make it a long literal by appending L:
System.out.print(prefixMatched(4388576018402626L, 4388));
The JLS specifies this behavior in Section 3.10.1:
An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).
and
It is a compile-time error if a decimal literal of type int is larger than 2147483648 (231), or if the decimal literal 2147483648 appears anywhere other than as the operand of the unary minus operator (§15.15.4).
add L at the end of your literal :
4388576018402626L
You should use Long instead of Integer
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -263 and a maximum value of 263-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 264-1. The unsigned long has a minimum value of 0 and maximum value of 264-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.
You should use following to avoid exception:
System.out.print(prefixMatched(4388576018402626L, 4388));
The L indicates given value is long. You can use either l or L but I prefer to use L because it looks goods while looking code.
Source: Oracle Docs.
For this code, I would recommend using String instead of dealing with long and int. It's far easier when trying to match the first four digits, which can be isolated easily using String#substring: (String_name).substring(0,4) will be return first four digits of the String. This can then be parsed as an int using Integer#parseInt, or simply compared to another String (if the prefix were a String as well).

hex to int number format exception in java

I am getting a number format exception when trying to do it
int temp = Integer.parseInt("C050005C",16);
if I reduce one of the digits in the hex number it converts but not otherwise. why and how to solve this problem?
This would cause an integer overflow, as integers are always signed in Java. From the documentation of that method (emphasis mine):
An exception of type NumberFormatException is thrown if any of the following situations occurs:
The first argument is null or is a string of length zero.
The radix is either smaller than Character.MIN_RADIX or larger than Character.MAX_RADIX.
Any character of the string is not a digit of the specified radix, except that the first character may be a minus sign '-' ('\u002D') provided that the string is longer than length 1.
The value represented by the string is not a value of type int.
It would fit into an unsigned integer, though. As of Java 8 there's Integer.parseUnsignedInt (thanks, Andreas):
int temp = Integer.parseIntUnsigned("C050005C",16);
On earlier Java versions your best bet here might to use a long and then just put the lower 4 bytes of that long into an int:
long x = Long.parseLong("C050005C", 16);
int y = (int) (x & 0xffffffff);
Maybe you can even drop the bitwise "and" here, but I can't test right now. But that could shorten it to
int y = (int) Long.parseLong("C050005C", 16);
C050005C is 3226468444 decimal, which is more than Integer.MAX_VALUE. It won't fit in int.
Use this:
long temp = Long.parseLong("C050005C",16);
The signed int type ranges from 0x7FFFFFFF to -0x80000000.

Categories