Big integer multiplication in java - java

This is my own method and I am also using my own BigInt class I did everything but I cannot seem to find out where I am doing wrong if someone can help me, I will be really thankful.
public BigInt mul(BigInt o) {
int max = n.length > o.n.length ? n.length : o.n.length;
int[] newdigits = new int[n.length + o.n.length];
for (int i = 0; i < max; i++)
{
int carry = 0;
for (int i2 = 0; i2 < o.n.length || carry > 0; i2++)
{
int otherDigit = i2 >= o.n.length ? 0: o.n[i2];
int val = (n[i] * otherDigit) + carry;
newdigits[i + i2] += val % 10;
carry = val / 10;
}
}
return new BigInt(newdigits);
}
This is my code so far it works but in the result i get one extra zero, as an example: when i multiply 100*10 I get 01000 instead of 1000 and other issue is that when i multiply 9999*1999 I get this: 1817262619101 but the correct answer is 19988001.
Can some one help me on this?
Here is my BigInt class:
public class BigInt {
public static void main(String[] args) {
BigInt a = new BigInt(args.length == 2 ? args[0] : "9999");
BigInt b = new BigInt(args.length == 2 ? args[1] : "1999");
System.out.println(a + (a.equals(b) ? " equals " : " does not equal ") + b);
System.out.println(a + (a.compareTo(b) < 0 ? " < " : (a.compareTo(b) > 0 ? " > " : " = ")) + b);
System.out.println(a + " + " + b + " = " + a.add(b));
if (a.compareTo(b) >= 0) {
System.out.println(a + " - " + b + " = " + a.sub(b));
}
System.out.println(a + " * " + b + " = " + a.mul(b));
if (a.compareTo(b) >= 0) {
System.out.println(a + " / " + b + " = " + a.div(b));
}
}
}
final class BigInt implements Comparable<BigInt> {
int[] digits;
int size;
public BigInt() {
n = new int[1];
}
public BigInt(String s) {
n = new int[s.length()];
for (int i = 0; i < n.length; ++i) {
n[n.length - i - 1] = s.charAt(i) - '0';
}
n = trim(n);
}
private BigInt(int[] n) {
this.n = new int[n.length];
for (int i = 0; i < n.length; ++i) {
this.n[i] = n[i];
}
}
public BigInt add(BigInt o) {
return null;
}
public int compareTo(BigInt o) {
if (n.length < o.n.length) {
return -1;
}
else if (n.length > o.n.length) {
return +1;
}
for (int i = n.length-1; i >= 0; --i) {
if (n[i] < o.n[i]) {
return -1;
}
else if (n[i] > o.n[i]) {
return +1;
}
}
return 0;
}
public BigInt div(BigInt o) {
return null;
}
public boolean equals(Object o) {
if (o instanceof BigInt) {
if (n.length == ((BigInt)o).n.length) {
for (int i = 0; i < n.length; ++i) {
if (n[i] != ((BigInt)o).n[i]) {
return false;
}
}
return true;
}
}
return false;
}
public BigInt mul(BigInt o) {
int max = n.length > o.n.length ? n.length : o.n.length;
int[] newdigits = new int[n.length + o.n.length];
for (int i = 0; i < max; i++)
{
int carry = 0;
for (int i2 = 0; i2 < o.n.length || carry > 0; i2++)
{
int otherDigit = i2 >= o.n.length ? 0: o.n[i2];
int val = (n[i] * otherDigit) + carry;
newdigits[i + i2] += val % 10;
carry = val / 10;
}
}
return new BigInt(newdigits);
}
public BigInt sub(BigInt o) {
return null;
}
public String toString() {
String s = "";
for (int i : n) {
s = i + s;
}
return s;
}
private int[] trim(int[] nums) {
int size = nums.length;
for (int i = nums.length - 1; i > 0; --i) {
if (nums[i] != 0) {
break;
}
--size;
}
int[] res = new int[size];
for (int i = 0; i < size; ++i) {
res[i] = nums[i];
}
return res;
}
private int[] n;
}

Didn't feel like debugging your code, but here is how I'd implement that multiplication. It's a little less efficient, but easier to keep track of the carry.
public BigInt mul(BigInt o) {
int max = n.length > o.n.length ? n.length : o.n.length;
int[] newdigits = new int[n.length + o.n.length];
for (int i = 0; i < max; i++) {
for (int i2 = 0; i2 < max; i2++) {
int digit1 = i >= n.length ? 0 : n[i];
int digit2 = i2 >= o.n.length ? 0 : o.n[i2];
if (digit1 > 0 && digit2 > 0) {
int value = digit1 * digit2;
int pos = i + i2;
while (value > 0) {
int newDigit = (newdigits[pos] + value) % 10;
value = (newdigits[pos] + value) / 10;
newdigits[pos] = newDigit;
pos++;
}
}
}
}
return new BigInt(newdigits);
}

First, look the possible lengths:
[1] * [1] = [1] OR length(1) + length(1) -> length(1)
[9] * [9] = [8,1] OR length(1) + length(1) -> length(2)
One solution
Psudocode:
if (newdigits[ (length-1) ] == 0)
int[] newarray = new int[ (length-1) ]
copy newdigits to newarray
return newarray
You have to look at the carry of the largest digit before the earlier digits.
Secondly, you need to add the previous value you found to the val variable.
End of i=0:
[1, 9, 9, 7, 1, 0, 0, 0]
Adding during i=1:
[0, 1, 9, 9, 7, 1, 0, 0]
End of i=1:
[1, 10, 18, 16, 8, 1, 0, 0]
I suggest you try using Arrays.toString(newdigits) or use a debugger to catch these problems in the future.

Related

How can I output the points that are colinear?

THE PROBLEM: Write a program that reads N points in a plane and outputs any group of four or more colinear points
What I did: I calculated the slope of every 2 points and then put them in a hashmap to see which one is the max.
What I need to do: I need to output the points that are colinear from the initial 2D array. I found the number of points that are colinear with the hashmap.
import java.util.*;
public class app {
public static int maxPoints(int[][] points) {
int ans = 1;
int n = points.length;
for (int i = 0; i < n; i++) {
HashMap<String, Integer> map = new HashMap<>();
int OLP = 0;
int max = 0;
for (int j = i + 1; j < n; j++) {
if (points[i][0] == points[j][0] && points[i][1] == points[j][1]) {
OLP++;
continue;
}
int dy = points[j][1] - points[i][1];
int dx = points[j][0] - points[i][0];
int g = gcd(Math.abs(dy), Math.abs(dx));
int num = dy / g;
int deno = dx / g;
if (num == 0)
deno = 1;
if (deno == 0)
num = 1;
if ((num < 0 && deno < 0) || deno < 0) {
num *= -1;
deno *= -1;
}
map.put(createString(deno, num), map.getOrDefault(createString(deno, num), 0) + 1);
max = Math.max(max, map.get(createString(deno, num)));
}
ans = Math.max(ans, 1 + OLP + max);
}
return ans;
}
public static int gcd(int a, int b) {
if (a == 0)
return b;
if (b == 0)
return a;
int max = Math.max(a, b);
int min = Math.min(a, b);
return gcd(max % min, min);
}
public static String createString(int a, int b) {
return Integer.toString(a) + " " + Integer.toString(b);
}
public static void main(String[] args) {
int[][] points = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 4 } };
System.out.println("max Points are: " + maxPoints(points));
}}

splitting binary string such that it is a power of 5

I am trying to split a binary string such that it is a possible to cut string into smallest positive integer, each of them being the power of 5. If there is no such pieces return -1 instead.
public class Power {
public int numsOfWays(String s) {
long[] f = new long[s.length() + 1];
f[0] = 0;
for (int i = 1; i <= s.length(); ++i) {
f[i] = Integer.MAX_VALUE;
for (int j = 1; j <= i; ++j) {
if (s.charAt(j - 1) == '0') {
continue;
}
int num = Integer.parseInt(s.substring(j - 1, i), 2);
if (isPower(num)) {
f[i] = Math.min(f[i], f[j - 1] + 1);
}
}
}
return f[s.length()] == Integer.MAX_VALUE ? -1 : (int) f[s.length()];
}
private boolean isPower(long val) {
if (val == 0) {
return false;
}
int n = (int) (Math.log(val) / Math.log(5));
return Math.pow(5, n) == val;
}
public static void main(String[] args) {
Power b = new Power();
System.out.println(b.numsOfWays("111011100110101100101110111"));
}
}
I am getting this error :-
Exception in thread "main" java.lang.NumberFormatException: For input string: "11101110011010110010111011100000"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:583)
at abc.Power.numsOfWays(Power.java:13)
at abc.Power.main(Power.java:33)
The Problem is in Line 13 of your code:
The line:
int num = Integer.parseInt(s.substring(j - 1, i), 2);
has a problem because the value is too long for intto handle.
Change it to:
long num = Long.parseLong(s.substring(j - 1, i), 2);
and it should work.
EDIT: The Entire Code looks like this:
public class Power {
public int numsOfWays(String s) {
long[] f = new long[s.length() + 1];
f[0] = 0;
for (int i = 1; i <= s.length(); ++i) {
f[i] = Integer.MAX_VALUE;
for (int j = 1; j <= i; ++j) {
if (s.charAt(j - 1) == '0') {
continue;
}
long num = Long.parseLong(s.substring(j - 1, i), 2);
if (isPower(num)) {
f[i] = Math.min(f[i], f[j - 1] + 1);
}
}
}
return f[s.length()] == Integer.MAX_VALUE ? -1 : (int) f[s.length()];
}
private boolean isPower(long val) {
if (val == 0) {
return false;
}
int n = (int) (Math.log(val) / Math.log(5));
return Math.pow(5, n) == val;
}
public static void main(String[] args) {
Power b = new Power();
System.out.println(b.numsOfWays("111011100110101100101110111")); // 5
System.out.println(b.numsOfWays("11111111111111111111111111111111111111111111111111")); // 50
}
}
And the output is:
5
50

How to increment integer Array values?

I am designing a problem in which I have to use an int array to add or subtract values. For example instead of changing 100 to 101 by adding 1, I want to do the same thing using the int array. It work like this:
int[] val = new int[3];
val[0] = 1;
val[1] = 0;
val[2] = 0;
val[2] += 1;
so, If I have to get a value of 101, I will add 1 to val[2].
The only problem I have is finding a way to make int array work like how adding and subtracting from an ordinary integer data set works.
Is this possible using a for loop or a while loop?
Any help will be appreciated!
Here's your homework:
public static int[] increment(int[] val) {
for (int i = val.length - 1; i >= 0; i--) {
if (++val[i] < 10)
return val;
val[i] = 0;
}
val = new int[val.length + 1];
val[0] = 1;
return val;
}
Make sure you understand how and why it works before submitting it as your own work.
Solution of this problem is designed by using String
You can refer to this method which will return sum of 2 nos having input in String format.
Input String should contain only digits.
class Demo {
public static String add(String a1, String b1) {
int[] a = String_to_int_Array(a1);
int[] b = String_to_int_Array(b1);
int l = a.length - 1;
int m = b.length - 1;
int sum = 0;
int carry = 0;
int rem = 0;
String temp = "";
if (a.length > b.length) {
while (m >= 0) {
sum = a[l] + b[m] + carry;
carry = sum / 10;
rem = sum % 10;
temp = rem + temp;
m--;
l--;
}
while (l >= 0) {
sum = a[l] + carry;
carry = sum / 10;
rem = sum % 10;
temp = rem + temp;
l--;
}
if (carry > 0) {
temp = carry + temp;
}
} else {
while (l >= 0) {
sum = a[l] + b[m] + carry;
carry = sum / 10;
rem = sum % 10;
temp = rem + temp;
m--;
l--;
}
while (m >= 0) {
sum = b[m] + carry;
carry = sum / 10;
rem = sum % 10;
temp = rem + temp;
m--;
}
if (carry > 0) {
temp = carry + temp;
}
}
return temp;
}
public static int[] String_to_int_Array(String s) {
int arr[] = new int[s.length()], i;
for (i = 0; i < s.length(); i++)
arr[i] = Character.digit(s.charAt(i), 10);
return arr;
}
public static void main(String a[]) {
System.out.println(add("222", "111"));
}
}
Quick & dirty:
static void increment(int[] array){
int i = array.length-1;
do{
array[i]=(array[i]+1)%10;
}while(array[i--]==0 && i>=0);
}
Note the overflow when incementing e.g. {9, 9}. Result is {0, 0} here.
public static void increment() {
int[] acc = {9,9,9,9};
String s="";
for (int i = 0; i < acc.length; i++)
s += (acc[i] + "");
int i = Integer.parseInt(s);
i++;
System.out.println("\n"+i);
String temp = Integer.toString(i);
int[] newGuess = new int[temp.length()];
for (i = 0; i < temp.length(); i++)
{
newGuess[i] = temp.charAt(i) - '0';
}
printNumbers(newGuess);
}
public static void printNumbers(int[] input) {
for (int i = 0; i < input.length; i++) {
System.out.print(input[i] + ", ");
}
System.out.println("\n");
}
If someone is looking for this solution using JavaScript or if you can translate it to java, here's your optimum solution:
function incrementArr(arr) {
let toBeIncrementedFlag = 1, // carry over logic
i = arr.length - 1;
while (toBeIncrementedFlag) {
if (arr[i] === 9) {
arr[i] = 0; // setting the digit as 0 and using carry over
toBeIncrementedFlag = 1;
} else {
toBeIncrementedFlag = 0;
arr[i] += 1;
break; // Breaking loop once no carry over is left
}
if (i === 0) { // handling case of [9,9] [9,9,9] and so on
arr.unshift(1);
break;
}
i--; // going left to right because of carry over
}
return arr;
}

Can you quickly tell me if this pseudocode makes sense or not?

I believe my code is now foolproof. I will write up the pseudocode now. But I do have one question. Why does DRJava ask that I return something outside of my if statements? As you can see I wrote for ex: "return 1;" just because it asked. It will never return that value however. Can someone explain this to me?
public class assignment1question2test {
public static void main(String[] args) {
int[] a = new int[50];
int l = 0;
int r = a.length;
for(int i=0; i<r; i++) {
a[i] = 1;
}
a[0] = 10;
for (int i=0; i<r; i++) {
System.out.println(a[i]);
}
System.out.print(recursiveSearch(a,l,r));
}
public static int recursiveSearch (int[] a, int l, int r) {
int third1 = (r-l)/3 + l;
int third2 = third1*2 - l + 1;
System.out.println("i will be checking compare from " + l + " to " + third1 + " and " + (third1 + 1) + " to " + third2);
int compareResult = compare(a,l,third1,third1 + 1, third2);
if(r-l == 1) {
if (compareResult == 1) {
return l;
}
else {
return r;
}
}
if (compareResult == 0) {
return recursiveSearch(a,third2 + 1, r);
}
if (compareResult == 1) {
return recursiveSearch(a,l,third1);
}
if (compareResult == -1) {
return recursiveSearch(a,third1 + 1, third2);
}
return 1;
}
public static int compare(int[] a, int i, int j, int k, int l) {
int count1 = 0;
int count2 = 0;
for(int g=i; g<=j; g++) {
count1 = count1 + a[g];
}
for(int g=k; g<=l; g++) {
count2 = count2 + a[g];
}
if (count1 == count2) {
return 0;
}
if (count1 > count2) {
return 1;
}
if (count1 < count2) {
return -1;
}
return 0;
}
}
UPDATED FINAL PSEUDOCODE:
Algorithm: recursiveSearch (a,l,r)
Inputs: An array a, indices l and r which delimit the part of interest.
Output: The index that has the lead coin.
int third1 ← (r - l + 1)/3
int third2 ← third1*2 - l + 1
if (r-l = 0) then
return l
int compareResult ← compare(a,l,third1,third1 + 1,third2)
if (r-l = 1) then
if (compareResult = 1) then
return l
else
return r
if (compareResult = 0) then
return recursiveSearch(a, third2 + 1, r)
if (compareResult = "1") then
return recursiveSearch(a,l,third1)
if (compareResult = "-1") then
return recursiveSearch(a,third1 + 1,third2)
You seem to be including mid in the following search regardless of which side is larger. The recursive calls should both exclude mid from their search space.
Also, for the comparison to be meaningful, the two groups being compared need to be of equal size. That will require some extra odd/even logic.

Java: How to sum the elements of two arrays with different lengths

I am trying to add the elements of two arrays with different lengths together.
The code below is only for the same length and here is all I have so far.
//for the same lengths
int[]num1 = {1,9,9,9};
int[]num2 = {7,9,9,9};// {9,9,9}
int total = 0, carry = 1;
int capacity = Math.max(num1.length,num2.length);
int []arraySum = new int [capacity];
for (int i = capacity - 1 ; i >= 0; i--)
{
arraySum[i] = num1[i]+ num2[i];
if (arraySum[i] > 9)
{
arraySum[i] = arraySum[i] % 10;
num2[i-1] = num2[i-1] + carry;
}
}
for(int i = 0; i < arraySum.length; i++)
{
System.out.print(arraySum[i]);
}
What should I do if I change the elements in num2 and length to like {9,9,9}?
I know I probably need to put another for-loop as an inside for-loop and control the indices of the array with smaller length but how....?? One more thing... what should I do for those for-loops conditions because num1 and num2 will be eventually INPUTED by the user.
Well, you can tell that the inputs are limited because if num1[0] + num2[0] > 9 the carry has no index to be placed, then it can't be compiled. So, I need to shift the whole array to the right and place the carry from num1[0] + num2[0]. Here is the problem!! Where should I put the shifting code? I am kinda confused.......
Actually, you declare an int[] array with the capacity as Math.max(num1.length, num2.length).
It is not encough. You should set the capacity as Math.max(num1.length, num2.length) +1.
Why?
See if num1 is {1,9,9,9} and num2 is {9,9,9,9}, how can the arraySum to represent the sum {1,1,9,9,8}?
So we need to declare it as below to consider if carry is needed.
int[] arraySum = new int[capacity + 1];
Then when print the sum, check if arraySum[0] is 0 or 1, if it euqals to 0, do not print it in Console.
Modified code for reference is as follows:
package question;
public class Example {
public static void main(String[] args) {
// for the same lengths
int[] num1 = { 1,9,9,9 };
int[] num2 = { 9,9,9,9};// {9,9,9}
// 1999+9999 = 11998, its length is greater than the max
int capacity = Math.max(num1.length, num2.length);
int[] arraySum = new int[capacity + 1];
int len2 = num2.length;
int len1 = num1.length;
if (len1 < len2) {
int lengthDiff = len2 - len1;
/*
* Flag for checking if carry is needed.
*/
boolean needCarry = false;
for (int i = len1 - 1; i >= 0; i--) {
/**
* Start with the biggest index
*/
int sumPerPosition =0;
if (needCarry) {
sumPerPosition = num1[i] + num2[i + lengthDiff] +1;
needCarry = false;
}else
{
sumPerPosition = num1[i] + num2[i + lengthDiff];
}
if (sumPerPosition > 9) {
arraySum[i + lengthDiff + 1] = sumPerPosition % 10;
needCarry = true;
}else
{
arraySum[i + lengthDiff + 1] = sumPerPosition % 10;
}
}
/**
* Handle the remaining part in nun2 Array
*/
for (int i = lengthDiff - 1; i >= 0; i--) {
/*
* Do not need to care num1 Array Here now
*/
if(needCarry){
arraySum[i + 1] = num2[i]+1;
}else
{
arraySum[i + 1] = num1[i] ;
}
if (arraySum[i + 1] > 9) {
arraySum[i + 1] = arraySum[i + 1] % 10;
needCarry = true;
} else {
needCarry = false;
}
}
/*
* Handle the last number, if carry is needed. set it to 1, else set
* it to 0
*/
if (needCarry) {
arraySum[0] = 1;
} else {
arraySum[0] = 0;
}
} else {
int lengthDiff = len1 - len2;
/*
* Flag for checking if carry is needed.
*/
boolean needCarry = false;
for (int i = len2 - 1; i >= 0; i--) {
/**
* Start with the biggest index
*/
int sumPerPosition = 0;
if (needCarry) {
sumPerPosition = num2[i] + num1[i + lengthDiff] +1;
needCarry = false;
}else
{
sumPerPosition = num2[i] + num1[i + lengthDiff];
}
if (sumPerPosition > 9) {
arraySum[i + lengthDiff + 1] = sumPerPosition % 10;
needCarry = true;
}else
{
arraySum[i + lengthDiff + 1] = sumPerPosition % 10;
}
}
/**
* Handle the remaining part in nun2 Array
*/
for (int i = lengthDiff - 1; i >= 0; i--) {
/*
* Do not need to care num1 Array Here now
*/
if(needCarry){
arraySum[i + 1] = num1[i]+1;
}else
{
arraySum[i + 1] = num1[i] ;
}
if (arraySum[i + 1] > 9) {
arraySum[i + 1] = arraySum[i + 1] % 10;
needCarry = true;
} else {
needCarry = false;
}
}
/*
* Handle the last number, if carry is needed. set it to 1, else set
* it to 0
*/
if (needCarry) {
arraySum[0] = 1;
} else {
arraySum[0] = 0;
}
}
/*
* Print sum
*
* if arraySum[0] ==1, print 1
*
* Do not print 0 when arraySum[0] ==0
*/
if(arraySum[0] == 1)
{
System.out.print(1);
}
for (int i = 1; i < arraySum.length; i++) {
System.out.print(arraySum[i]);
}
}
}
An example that num1 is {1,9,9,9} and num2 is {9,9,9,9}, the sum result is as follows:
output in Console:
11998
It's quite simpe actually. Inside your loop, check that the current index is valid for both array, and replace the value to add by 0 in case of an invalid index:
int value1 = (i < num1.length) ? num1[i] : 0;
int value2 = (i < num2.length) ? num2[i] : 0;
arraySum[i] = value1 + value2;
EDIT: I didn't understand that you wanted to right-align the arrays and not left-align them. The simplest solution is probably to write and read everything in the arrays in reverse order. So if the numbers are 456 and 7658, the first array would contain 6, 5, 4 and the second one would contain 8, 5, 6, 7.
Here is more performance centric solution:
public class SumArrays {
public static void main(String[] args) {
int[] num1 = {1, 9, 9, 9};
int[] num2 = {7, 9, 9, 9, 9, 9, 9};
int[] biggerArray = num1.length > num2.length ? num1 : num2;
int[] smallerArray = num1.length <= num2.length ? num1 : num2;
int[] summedArray = new int[biggerArray.length];
System.arraycopy(biggerArray, 0, summedArray, 0, biggerArray.length);
for (int i = 0; i < smallerArray.length; i++) {
summedArray[i] += smallerArray[i];
}
for (int i = 0; i < summedArray.length; i++) {
System.out.println(summedArray[i]);
}
}
}
You can use an ArrayList instead of an array and implement a normal addition method to it:
public static ArrayList<Integer> sum(int[] arr, int[] arr2) {
ArrayList<Integer> al = new ArrayList<>();
int i = arr.length - 1;
int j = arr2.length - 1;
int c = 0;
while (i >= 0 && j >= 0) {
int temp = arr[i] + arr2[j] + c;
if (temp >= 10) {
int r = temp % 10;
al.add(0, r);
c = temp / 10;
} else {
al.add(0, temp);
c = 0;
}
i--;
j--;
}
if (i < 0 && j >= 0) {
while (j >= 0) {
al.add(0, arr2[j] + c);
c = 0;
j--;
}
} else if (j < 0 && i >= 0) {
while (i >= 0) {
al.add(0, arr[i] + c);
c = 0;
i--;
}
} else
al.add(0, c);
return al;
}
for kicks, here is an alternative:
int[] num1 =
{ 1, 9, 9, 9 };
int[] num2 =
{ 7, 9, 9, 9 };
//convert the int array to a string
StringBuilder sb = new StringBuilder(num1.length);
for (int i : num1)
{
sb.append(i);
}
String sNum1 = sb.toString();
System.out.println(sNum1);
StringBuilder sb2 = new StringBuilder(num2.length);
for (int i : num2)
{
sb2.append(i);
}
String sNum2 = sb2.toString();
System.out.println(sNum2);
try
{
//parse the string to an int
int iNum1 = Integer.parseInt(sNum1);
int iNum2 = Integer.parseInt(sNum2);
//add them together
int sum = iNum1 + iNum2;
String sSum = Integer.toString(sum);
System.out.println(sSum);
// convert num back to array
int[] sumArray = new int[sSum.length()];
for (int i = 0; i < sSum.length(); i++)
{
sumArray[i] = sSum.charAt(i) - '0';
System.out.println(sumArray[i]);
}
}
catch (Exception e)
{
// couldnt parse ints
}

Categories