I have a problem with remainder operator in java:
Why this:
(int)2147483648l % 10
gives a negative number (-8)?
That's because (int) 2147483648l is -2147483648. You're casting the long to int and it is out of bounds.
Casting problem .Data loss due to narrowing. You are converting long to int.
Read more about conversion.
From JLS
The remainder operation for operands that are integers after binary numeric promotion (§5.6.2) produces a result value such that (a/b)*b+(a%b) is equal to a.
from Narrowing Primitive Conversions JLS 5.1.3
So 2147483648l will cast into int that will be -2147483648 and then based on (a/b)*b+(a%b) = a
Value should be -8 what you are getting.
use "long" in place of "int".
you can use it without typecasting also
Following Example might be useful:
public class Example1
{
public static void main(String args[])
{
int b = (int)2147483648l;
System.out.println("Value of b: "+ b);
System.out.println("Output1: "+b % 10);
long a = 2147483648l;
System.out.println("Value of a: "+ a);
System.out.println("Output2: "+ a % 10);
}
}
output
Value of b: -2147483648
Output1: -8
Value of a: 2147483648
Output2: 8
You're getting a negative number because you're converting a long to an int. A possible work around in your case simply takes advantage of the fact that any decimal x mod 10 is simply the digit in the lowest decimal place (in the ones place). For example, 156 mod 10 is 6, because 156 divided by 10 is 15 + (6/10). So you could do something like this
//get the number and make it a string
String numberAsString = String.valueOf(number);
//get the integer value of the last character in the string (basically the lowest place)
int mod10 = Integer.parseInt(numberAsString.charAt(numberAsString.length() - 1));
This works for any integer number as long as what you want is number % 10
Related
With below code sample why the first addition (1/2+1/2) prints 0 but the second addition prints 00.
System.out.println(1/2+1/2+"=1/2+1/2");
System.out.println("1/2+1/2="+1/2+1/2);
Output:
0=1/2+1/2
1/2+1/2=00
Integer math (int 1 divided by int 2 is int 0, if you want a floating point result cast one, or both, of 1 and 2 to a floating point type) and order of operations, the second example is String concatenation. The compiler turns that into
System.out.println(new StringBuilder("1/2+1/2=").append(1/2).append(1/2));
and then you get
System.out.println(new StringBuilder("1/2+1/2=").append(0).append(0));
The first statement "System.out.println(1/2+1/2+"=1/2+1/2");" prints 0 because an the integer value obtained from 1/2 is zero. The remainder is dropped and since 1/2 equals 0.5 the .5 is dropped.
The second statement "System.out.println("1/2+1/2="+1/2+1/2);" prints out 00 because of the concatenation sign. In the second statement the first integer 1 is shown as +1 so the statement is actually being read as (+1/2 +1/2) which is why it returns 00.
If the second statement was set up like this:
System.out.println("1/2+1/2="+ (1/2+1/2));
The output would be the same as the first statement.
Expression is evaluated from left to right. In the first case it does int+int (which is 0), then int + "= String" which is a String tmp = "0= String". In the other case you have '"String =" + intwhich becomes"String =int"to which you append one moreint`. Thus you print String, "0" and "0".
java assumes that the result of the division is integer , since its members are integers. For the floating result ( 0.5 ) of each division , the divisor or the dividend should be of type float
System.out.println("1/2+1/2="+(1/2.0+1/2.0));
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)
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).
Why does this code throw a NumberFormatException :
String binStr = "1000000000000000000000000000000000000000000000000000000000000000";
System.out.println(binStr.length());// = 64
System.out.println(Long.parseLong(binStr, 2));
1000000000000000000000000000000000000000000000000000000000000000 is larger than Long.MAX_VALUE.
See https://stackoverflow.com/a/8888969/597657
Consider using BigInteger(String val, int radix) instead.
EDIT:
OK, this is new for me. It appears that Integer.parseInt(binaryIntegerString, 2) and Long.parseLong(binaryLongString, 2) parse binary as sign-magnitude not as a 2's-complement.
Because it's out of range. 1000...000 is 263, but Long only goes up to 263 - 1.
This is the same for all of Long, Integer, Short and Byte. I'll explain with a Byte example because it's readable:
System.out.println(Byte.MIN_VALUE); // -128
System.out.println(Byte.MAX_VALUE); // 127
String positive = "1000000"; // 8 binary digits, +128
String negative = "-1000000"; // 8 binary digits, -128
String plus = "+1000000"; // 8 binary digits, +128
Byte.parseByte(positive, 2); //will fail because it's bigger than Byte.MAX_VALUE
Byte.parseByte(negative, 2); //won't fail. It will return Byte.MIN_VALUE
Byte.parseByte(plus, 2); //will fail because its bigger than Byte.MAX_VALUE
The digits are interpreted unsigned, no matter what radix is provided. If you want a negative value, you have to have the minus sign at the beginning of the String. JavaDoc says:
Parses the string argument as a signed long in the radix specified by
the second argument. The characters in the string must all be digits
of the specified radix (as determined by whether Character.digit(char, int) returns a nonnegative value), except that the first character may
be an ASCII minus sign '-' ('\u002D') to indicate a negative value or
an ASCII plus sign '+' ('\u002B') to indicate a positive value. The
resulting long value is returned.
In order to get MAX_VALUE we need:
String max = "1111111"; // 7 binary digits, +127
// or
String max2 = "+1111111"; // 7 binary digits, +127
Largest long value is actually:
0111111111111111111111111111111111111111111111111111111111111111b = 9223372036854775807
This is because Long.parseLong cannot parse two's complement representation. The only way to parse two's complement binary string representation in Java SE is BigInteger:
long l = new BigInteger("1000000000000000000000000000000000000000000000000000000000000000", 2).longValue()
this gives expected -9223372036854775808result
This is the largest possible long (9223372036854775807 = 2 exp 63 - 1) in binary format. Note the L at the end of the last digit.
long largestLong = 0B0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L;
Actually, this is works for me:
String bitStr = "-1000000000000000000000000000000000000000000000000000000000000000";
System.out.println(Long.parseLong(bitStr, 2));
Here is a thing: inside Long.parseLong() code logic is looking for explicit sign first. And respectively to the sign, different limits are used (Long.MAX_VALUE for positive, and Long.MIN_VALUE for negative binary literals). Probably it would be better if this logic looked up first to the eldest bit (0 for positive and 1 for negative numbers) the sign
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.