I'm totally new to Java and I'm implementing a simple function to convert string to integer on Leetcode.
public int myAtoi(String str) {
if(str.length() == 0){
return 0;
}
str = str.trim();
int n = str.length();
int signal = 0;
if(n == 1 && str.equals("+") || str.equals("-")){
return 0;
}
if(str.charAt(0) == '+'){
signal = 1;
}else if(str.charAt(0) == '-'){
signal = -1;
}
int i = (signal != 0)? 1 : 0;
if(signal == 0){
signal = 1;//default
}
int res = 0;
while(i < n){
char c = str.charAt(i);
if(!Character.isDigit(c)){
return res * signal;
}
//res = res * 10 + c - '0';
if(signal * res > Integer.MAX_VALUE){
return Integer.MAX_VALUE;
}
if(signal * res < Integer.MIN_VALUE){
return Integer.MIN_VALUE;
}
res = res * 10 + c - '0';
++i;
}
return res * signal;
}
I know java integer has the MAX_VALUE of 2147483647. When my input is 2147483648 the output should be 2147483647 but indeed it's -214748648. I really have no idea what's wrong in here. Can anybody help me to understand this?
Consider this example
public static void main(String args[]) {
int i=2147483647;
System.out.println("i="+i);
int j=++i;
System.out.println("Now i is="+i);
System.out.println("j="+j);
}
What happens?
output will be :
i = 2147483647
Now i is=-2147483648
j=-2147483648
The maximum value of integer is 2,147,483,647 and the minimum value is -2,147,483,648. Here in j (with post increment of i), we have crossed the maximum limit of an integer
This is exactly what is happening in your case too .
Because the integer overflows. When it overflows, the next value is Integer.MIN_VALUE
Why?
Integer values are represented in binary form, and there is binary addition in java. It uses a representation called two's complement, in which the first bit of the number represents its sign. Whenever you add 1 to the largest Integer(MAX INT), which has a bit sign of 0, then its bit sign becomes 1 and the number becomes negative.
So, don't put > MAX INT as input, else put a condition in your code to check it on input itself.
The input is never +2147483648 since that value can't be represented as a Java int.
It will wrap around to the negative number you observe, so accounting for that result.
Related
I write down a code which find out quotient after dividing two number but without using multiplication,division or mod operator.
My code
public int divide(int dividend, int divisor) {
int diff=0,count=0;
int fun_dividend=dividend;
int fun_divisor=divisor;
int abs_dividend=abs(dividend);
int abs_divisor=abs(divisor);
while(abs_dividend>=abs_divisor){
diff=abs_dividend-abs_divisor;
abs_dividend=diff;
count++;
}
if(fun_dividend<0 && fun_divisor<0){
return count;
}
else if(fun_divisor<0||fun_dividend<0) {
return (-count);
}
return count;
}
My code passes the test cases like dividend=-1, divisor=1 or dividend=1 and divisor=-1. But it cannot pass the test case like dividend = --2147483648 and divisor =-1. However I have a if statement when both inputs are negative.
if(fun_dividend<0 && fun_divisor<0){
return count;
}
When my inputs are -2147483648 and -1 it returned zero. I debugged my code and find out that it cannot reach the the inner statements of while loop. It just check the while loop and terminated and execute
if(fun_dividend<0 && fun_divisor<0){
return count;
}
It is very obvious, both inputs are negative, so I was using Math.abs function to make them positive. But when I try to see the values of variables abs_dividend and abs_divisor they show me negative values.
Integer max can take a 9 digit number. So how could I pass this test case? As per this test case dividend is a 10 digit number which is not valid for a integer range.
As per the test case the output that I get should be 2147483647.
How could I solve the bug?
Thank you in advance.
Try using the bit manipulation for this as follows:
public static int divideUsingBits(int dividend, int divisor) {
// handle special cases
if (divisor == 0)
return Integer.MAX_VALUE;
if (divisor == -1 && dividend == Integer.MIN_VALUE)
return Integer.MAX_VALUE;
// get positive values
long pDividend = Math.abs((long) dividend);
long pDivisor = Math.abs((long) divisor);
int result = 0;
while (pDividend >= pDivisor) {
// calculate number of left shifts
int numShift = 0;
while (pDividend >= (pDivisor << numShift)) {
numShift++;
}
// dividend minus the largest shifted divisor
result += 1 << (numShift - 1);
pDividend -= (pDivisor << (numShift - 1));
}
if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) {
return result;
} else {
return -result;
}
}
I solve it this way. Give preference to data type long over int wherever there is a chance of overflow upon left-shift. Handle the edge case at the very beginning to avoid the input values getting modified in the process. This algorithm is based upon the division technique we used to make use in school.
public int divide(int AA, int BB) {
// Edge case first.
if (BB == -1 && AA == Integer.MIN_VALUE){
return Integer.MAX_VALUE; // Very Special case, since 2^31 is not inside range while -2^31 is within range.
}
long B = BB;
long A = AA;
int sign = -1;
if ((A<0 && B<0) || (A>0 && B>0)){
sign = 1;
}
if (A < 0) A = A * -1;
if (B < 0) B = B * -1;
int ans = 0;
long currPos = 1; // necessary to be long. Long is better for left shifting.
while (A >= B){
B <<= 1; currPos <<= 1;
}
B >>= 1; currPos >>= 1;
while (currPos != 0){
if (A >= B){
A -= B;
ans |= currPos;
}
B >>= 1; currPos >>= 1;
}
return ans*sign;
}
Ran with the debugger and found that abs_dividend was -2147483648.
Then the comparison in while (abs_dividend >= abs_divisor) { is false and count is never incremented.
Turns out the explanation is in the Javadoc for Math.abs(int a):
Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.
Presumably, this is because Integer.MAX_VALUE is 2147483647, so there is no way of representing positive 2147483648 with an int. (note: 2147483648 would be Integer.MAX_VALUE + 1 == Integer.MIN_VALUE)
I need to add two binary numbers and return the sum. No base conversions are allowed. I know the long method, using arrays. But is there anything shorter ? And by shorter I mean "having smaller code length". Thanks in advance.
In case I was not explicit enough, here is an example:
Input:
1101
11
Output: 10000
The sum of two (binary) integers a and b can be computed as a+b, because all arithmetic is done in binary.
If your input is in human readable strings rather than binary, you can compute their sum in binary using the standard BigInteger class:
import java.math.BigInteger;
String sum(String a, String b) {
return new BigInteger(a, 2).add(new BigInteger(b, 2)).toString(2);
}
Represent the binary numbers as two strings. Reverse the two strings. Then, you can iterate along both strings simultaneously, adding values to three arrays, two which represent the binary digit being added from the strings and the third to represent the carry digit. Create a fourth array representing the answer (you might have to find the limit for how long the answer can possibly be).
fill the answer array by using standard binary adding:
0 + 0 = 0 in the same position,
1 + 0 = 0 + 1 = 1 in the same position,
1 + 1 = 0 in the same position, and carry a 1 to the next position,
1 + 1 + 1 = 1 in the same position, and carry a 1 to the next position.
Reverse the array and you'll have the answer as a binary number.
Here are a couple options, not using any utility methods provided by Java. These don't account for sign (leading +/-) so they only handle whole numbers.
This first method converts the binary strings to integers, adds the integers, then converts the result back to binary. It uses a method-local inner class Convert to avoid duplicating the binaryToInt() code for each of the parameters.
static String binaryAdd1(String binary1, String binary2) {
class Convert {
int binaryToInt(String binary) {
int result = 0;
for (int i = 0; i < binary.length(); i++) {
char c = binary.charAt(i);
result *= 2;
if (c == '1') {
result++;
} else if (c != '0') {
throw new IllegalArgumentException(binary);
}
}
return result;
}
}
final Convert convert = new Convert();
int int1 = convert.binaryToInt(binary1);
int int2 = convert.binaryToInt(binary2);
String result = "";
int temp = int1 + int2;
do {
result = ((temp & 1) == 1 ? '1' : '0') + result;
temp >>= 1;
} while (temp > 0);
return result;
}
This second method uses binary addition logic, as specified by JHaps in his answer, to directly add together the two parameters. No intermediate conversion to integers here.
static String binaryAdd2(String binary1, String binary2) {
final String validDigits = "01";
String binarySum = "";
// pad the binary strings with one more significant digit for carrying
String bin1 = '0' + binary1;
String bin2 = '0' + binary2;
// add them together starting from least significant digit
int index1 = bin1.length() - 1;
int index2 = bin2.length() - 1;
boolean carry = false;
while (index1 >= 0 || index2 >= 0) {
char char1 = bin1.charAt(index1 >= 0 ? index1 : 0);
char char2 = bin2.charAt(index2 >= 0 ? index2 : 0);
if (validDigits.indexOf(char1) < 0)
throw new NumberFormatException(binary1);
if (validDigits.indexOf(char2) < 0)
throw new NumberFormatException(binary2);
if (char1 == char2) {
binarySum = (carry ? '1' : '0') + binarySum;
carry = char1 == '1';
} else {
binarySum = (carry ? '0' : '1') + binarySum;
}
index1--;
index2--;
}
if (binarySum.length() > 1 && binarySum.charAt(0) == '0') {
binarySum = binarySum.substring(1);
}
String result = binarySum.toString();
return result;
}
I have a serious problem. I need to get a number say
123454466666666666666665454545454454544598989899545455454222222222222222
and give the total of that number. I was trying for a long time. I couldn't get the answer. The problem is I didn't know which data type to use. I have tried it long. It accepts only 18 digits. I have gone through BigInteger. But I couldn't make arithmetic operations with it. so help me out with this problem..
1.Get it as a string
2.get length of it.
3.Loop through each character of it.
4.check if the character is a number.
5.If yes parse it to int.
6.Add all numbers together in the loop
OR
Use BigDecimal
You can get the result from the below code.
String string = "123454466666666666666665454545454454544598989899545455454222222222222222";
int count = 0;
for (int i = 0; i < string.length(); i++) {
count += Integer.parseInt(String.valueOf(string.charAt(i)));
}
System.out.println(count);
Just use it as a String. That's the easiest way to go for the task at hand.
public class Test022 {
public static void main(String[] args) {
String s = "123454466666666666666665454545454454544598989899545455454222222222222222";
int sum = 0;
for (int i=0; i<s.length(); i++){
sum += s.charAt(i) - '0';
}
System.out.println(sum);
}
}
i can suggest using this code and the numbers as String
/**
* Adds two non-negative integers represented as string of digits.
*
* #exception NumberFormatException if either argument contains anything other
* than base-10 digits.
*/
public static String add(String addend1, String addend2) {
StringBuilder buf = new StringBuilder();
for ( int i1 = addend1.length() - 1, i2 = addend2.length() - 1, carry = 0;
(i1 >= 0 && i2 >= 0) || carry != 0;
i1--, i2-- ) {
int digit1 = i1 < 0 ? 0 :
Integer.parseInt(Character.toString(addend1.charAt(i1)));
int digit2 = i2 < 0 ? 0 :
Integer.parseInt(Character.toString(addend2.charAt(i2)));
int digit = digit1 + digit2 + carry;
if (digit > 9) {
carry = 1;
digit -= 10;
} else {
carry = 0;
}
buf.append(digit);
}
return buf.reverse().toString();
}
BigInteger does support methods like add/multiply etc. See this for details.
BigInteger operand1 = new BigInteger("123454466666666666666665454545454454544598989899545455454222222222222222");
BigInteger operand2 = new BigInteger("123454466666666666666665454545454454544598989899545455454222222222222222");
System.out.println(operand1.add(operand2));
System.out.println(operand1.subtract(operand2));
System.out.println(operand1.multiply(operand2));
System.out.println(operand1.divide(operand2));
The title is pretty much self explanatory. :)
1232 => 0
1231030 => 1
2000 => 3
34444400000 => 5
If it fits into an int/long, just check if the number modulo 10 is 0 and keep a counter:
long x = ...
if (x == 0) {
return 0;
}
int counter = 0;
while (x % 10 == 0) {
counter++;
x /= 10;
}
If it's too big to fit in long, store it in a String and count zeroes from the last char:
String s = ...
int counter = 0;
while(counter < s.length() && s.charAt(s.length() - 1 - counter) == '0') {
counter++;
}
Integer class has an inbuilt function to count the trailing zeros.
javadocs
int trailingZeroes = Integer.numberOfTrailingZeros(int i);
Three lines:
int zeroes = 0
while(num%10 == 0 && num != 0) {
zeroes++;
num /= 10;
}
This uses the modulus operator. As long as we can divide by ten without remainder, increment the counter.
Here is another solution using Java 8 Streams:
int trailingZeros = String.valueOf(number).chars()
.reduce(0, (count, ch) -> (ch == '0') ? count + 1 : 0);
This transforms the number to an IntStream. This stream is then reduced using a lambda which resets a counter each time a non-zero char comes up.
You could always just use a regular expression:
Pattern pattern = Pattern.compile("(0+)$");
Matcher matcher = pattern.matcher(String.valueOf(123140000));
Integer trailingZeroes = 0;
if (matcher.find()) {
trailingZeroes = matcher.group(1).length();
}
System.out.println(trailingZeroes);
you can turn the int to a String and iterate in reverse, counting the zeros until you find a char that is not zero:
int countZeros(int x){
String a = Integer.toString(x);
int numOfZeros = 0;
for(int i = a.length() - 1; i >= 0; i--)
if (a.charAt(i) != '0') break;
else numOfZeros ++;
return numOfZeros;
}
Testing with :
System.out.println(countZeros(25000)); will print 3
System.out.println(countZeros(25)); will print 0
Hope this helps.
Not tried this code but this should work.
int counterForZeros=0;
for(long i=10;true;)
{
if(num%i==0)
{
counterForZeros++;
i*=10;
}
else
{
break;
}
}
System.out.println("Number of zeros in "+num+" is "+counterForZeros);
Well, if this is a contest to see who can do it in the fewest lines:
trailingZeroes = String.valueOf(num).length() - String.valueOf(num).replaceAll("0*$","").length();
I am trying to find a way to reverse a number without
Converting it to a string to find the length
Reversing the string and parsing it back
Running a separate loop to compute the Length
i am currently doing it this way
public static int getReverse(int num){
int revnum =0;
for( int i = Integer.toString(num).length() - 1 ; num>0 ; i-- ){
revnum += num % 10 * Math.pow( 10 , i );
num /= 10;
}
return revnum;
}
But I would Like to implement the above 3 conditions.
I am looking for a way , possibly using the bit wise shift operators or some other kind of bitwise operation.
Is it possible ? If so how ?
PS : If 1234 is given as input it should return 4321. I will only be reversing Integers and Longs
How about:
int revnum = 0;
while (num != 0) {
revnum = revnum * 10 + (num % 10);
num /= 10;
}
return revnum;
The code expects a non-negative input.
This may or may not matter to you, but it's worth noting that getReverse(getReverse(x)) does not necessarily equal x as it won't preserve trailing zeroes.
How about this? It handles negative numbers as well.
public int getReverse(int num){
int rst=0;
int sign;
sign=num>0?1:-1;
num*=sign;
while(num>0){
int lastNum = num%10;
rst=rst*10+lastNum
num=num/10;
}
return rst*sign;
}
Integer.MAX_VALUE or Integer.MIN_VALUE is not at all considered in any of the solutions.
For eg: if the input is -2147483647 or 2147483647 the o/p will be 1126087180 and -1126087180 respectively.
Please try the below solutions where both the conditions are handled, so if at any point of time the number is going beyond the boundary conditions i.e., INPUT_VALUE > Integer.MAX_VALUE or INPUT_VALUE < Integer.MIN_VALUE it would return 0
class ReversingIntegerNumber {
public int reverse(int originalNum) {
boolean originalIsNegative = originalNum > 0 ? false : true;
int reverseNum = 0;
int modValue;
originalNum = Math.abs(originalNum);
while(originalNum != 0) {
modValue = originalNum % 10;
if(reverseNum > (Integer.MAX_VALUE - modValue)/10) {
return 0;
}
reverseNum = (reverseNum * 10) + modValue;
originalNum /= 10;
}
return originalIsNegative ? -1 * reverseNum : reverseNum;
}
}