I have tried to convert ISBN10 codes to ISBN13 numbers with Java. From . On isbn-13.info I found the way to convert them.
Example: 0-123456-47-9
Begin with prefix of “978”
Use the first nine numeric characters of the ISBN (include dashes) 978-0-123456-47-
Calculate the EAN check digit using the “Mod 10 Algorithm” 978-0-123456-47-2
Using that I have created a Java program to do the conversion.
public class ISBNConverter {
public static void main(String[] args) {
String isbn10 = "9513218589";
String isbn13 = "";
int sum = 0;
int checkNumber = 0;
int multiplier = 2;
String code = "978" + isbn10.substring(0, isbn10.length() - 1);
for(int i = code.length() - 1; i >= 0; i--) {
int num = Character.getNumericValue(code.charAt(i));
isbn13 += String.valueOf(num * multiplier);
multiplier = (multiplier == 2) ? 1 : 2;
}
for(int i = 0; i < isbn13.length(); i++) {
sum += Character.getNumericValue(isbn13.charAt(i));
}
while(sum % 10 != 0) {
sum++;
checkNumber++;
}
System.out.println(checkNumber);
}
}
For the example ISBN10 code 9513218589 (978951321858 ISBN13 without the check number) it returns 5 as the check number. If I calculate it using the converter on ISBN's official site I get 4 as the check sum. For some reason, the sum of the numbers in the new code is one less than it should be.
I have being fighting with this for a long time and I believe I have began blind: I just can't find what I'm doing wrong. Could someone help with this?
Here you go
public static String ISBN10toISBN13( String ISBN10 ) {
String ISBN13 = ISBN10;
ISBN13 = "978" + ISBN13.substring(0,9);
//if (LOG_D) Log.d(TAG, "ISBN13 without sum" + ISBN13);
int d;
int sum = 0;
for (int i = 0; i < ISBN13.length(); i++) {
d = ((i % 2 == 0) ? 1 : 3);
sum += ((((int) ISBN13.charAt(i)) - 48) * d);
//if (LOG_D) Log.d(TAG, "adding " + ISBN13.charAt(i) + "x" + d + "=" + ((((int) ISBN13.charAt(i)) - 48) * d));
}
sum = 10 - (sum % 10);
ISBN13 += sum;
return ISBN13;
}
pardon the log lines in between, I am copy pasting it from an android project i am working on
In the
for(int i = 0; i < isbn13.length(); i++) {
sum += Character.getNumericValue(isbn13.charAt(i));
}
You're adding up all the digits from the ISBN, including the doubled ones.
Example:
digit 7 -> double = 14
You're adding 14 to the sum. Is should be
digit 7 -> double = 14 -> bigger than 9? yes, so 1+4 = 5
and you should add 5.
You could use the Apache commons-validator library to do this for you. See the ISBNValidator::convertToISBN13 method.
import org.apache.commons.validator.routines.ISBNValidator;
String isbn13 = ISBNValidator.getInstance().convertToISBN13("9513218589");
It's really easy.
Please look at my JavaScript example to understand the logic of conversion:
function isbn13to10(isbn13) {
var digits = [];
var sum = 0; var chk_tmp, chk_digit;
digits = (isbn13 + "").substr(3,9).split("") ;
for(var i = 0; i < 9; i++) {
sum += digits[i] * (10 - i);
}
chk_tmp = 11 - (sum % 11);
if (chk_tmp == 10) {
chk_digit = 'x';
} else if (chk_tmp == 11) {
chk_digit = 0;
} else {
chk_digit = chk_tmp;
}
digits.push(chk_digit);
return digits.join("");
}
function isbn10to13(isbn10){
var sum = (isbn10 + "").charAt(9);
var mltp = 0;
var total = 0;
if (sum == "X") { sum = 10; }
isbn10 = "978"+isbn10.substring(0,9);
for (i=0; i<12; i++) {
mltp = (i % 2) == 0 ? 1 : 3;
total = total+(isbn10.charAt(i)*mltp);
}
sum = (10 - (total % 10)) % 10;
return isbn10+sum;
}
Related
I have given number and want it to return as a String in expanded form. For example
expandedForm(12); # Should return "10 + 2"
expandedForm(42); # Should return "40 + 2"
expandedForm(70304); # Should return "70000 + 300 + 4"
My function works for first and second case, but with 70304 it gives this:
70 + 00 + 300 + 000 + 4
Here's my code
import java.util.Arrays;
public static String expandedForm(int num)
{
String[] str = Integer.toString(num).split("");
String result = "";
for(int i = 0; i < str.length-1; i++) {
if(Integer.valueOf(str[i]) > 0) {
for(int j = i; j < str.length-1; j++) {
str[j] += '0';
}
}
}
result = Arrays.toString(str);
result = result.substring(1, result.length()-1).replace(",", " +");
System.out.println(result);
return result;
}
I think there's a problem with the second loop, but can't figure out why.
You should be adding '0's to str[i], not str[j]:
for(int i = 0; i < str.length-1; i++) {
if(Integer.valueOf(str[i]) > 0) {
for(int j = i; j < str.length-1; j++) {
str[i] += '0';
}
}
}
This will result in:
70000 + 0 + 300 + 0 + 4
You still have to get rid of the 0 digits.
One possible way to get rid of them:
result = result.substring(1, result.length()-1).replace(", 0","").replace(",", " +");
Now the output is
70000 + 300 + 4
Pseudocode uses integer arithmetics to extract decimal digits one-by-one (from the right one):
mul = 1 //will contain power of 10
while (num > 0):
dig = num % 10 //integer modulo retrieves the last digit
if (dig > 0): //filter out zero summands
add (dig * mul) to output //like 3 * 100 = 300
num = num / 10 //integer division removes the last decimal digit 6519 => 651
mul = mul * 10 //updates power of 10 for the next digit
You could do the same with pure math, using modulo % and integer division /, e.g. using Stream API:
int n = 70304;
String res = IntStream
.iterate(1, k -> n / k > 0, k -> k * 10) // divisors
.map(k -> (n % (k*10) / k ) * k) // get 1s, 10s, 100s, etc.
.filter(x -> x > 0) // throw out zeros
.mapToObj(Integer::toString) // convert to string
.collect(Collectors.joining(" + ")); // join with '+'
System.out.println(res); // 4 + 300 + 70000
There are many variations possible. If the usage of a list is allowed:
public static String expandedForm(int num){
String[] str = Integer.toString(num).split("");
String result;
List<String> l = new ArrayList<String>();
for(int i = 0; i < str.length; i++){
if(Integer.valueOf(str[i]) > 0){
String s = str[i];
for(int j = i; j < str.length - 1; j++){
s += '0';
}
l.add(s);
}
}
result = l.toString();
result = result.substring(1, result.length() - 1).replace(",", " +");
System.out.println(result);
return result;
}
One could also work directly on result:
public static String expandedForm2(int num){
String[] str = Integer.toString(num).split("");
String result = "";
for(int i = 0; i < str.length; i++){
if(Integer.valueOf(str[i]) > 0){
result += str[i];
for(int j = i; j < str.length - 1; j++){
result += '0';
}
result += " + ";
}
}
result = result.substring(0, result.length() - 3);
System.out.println(result);
return result;
}
This is also possible to do recursively. Here an example implementation:
String g(int n, int depth){ // Recursive method with 2 int parameters & String return-type
int remainder = n % depth; // The current recursive remainder
if(depth < n){ // If we aren't done with the number yet:
int nextDepth = depth * 10; // Go to the next depth (of the power of 10)
int nextN = n - remainder; // Remove the remainder from the input `n`
// Do a recursive call with these next `n` and `depth`
String resultRecursiveCall = g(nextN, nextDepth);
if(remainder != 0){ // If the remainder was not 0:
// Append a " + " and this remainder to the result
resultRecursiveCall += " + " + remainder;
}
return resultRecursiveCall; // And return the result
} else{ // Else:
return Integer.toString(n); // Simply return input `n` as result
}
}
String f(int n){ // Second method so we can accept just integer `n`
return g(n, 1); // Which will call the recursive call with parameters `n` and 1
}
The second method is so we can call the method with just a single input n. For example:
String result = f(70304);
Which will result in the String 70000 + 300 + 4.
Try it online.
To explain a bit more in depth of what this recursive method does, let's just do a step-by-step for the input 70304:
In the first recursive iteration: n=70304, depth=1, remainder=70304%1 = 0.
Since depth < n is truthy, it will do a recursive call with 70304-0 and 1*10
And since remainder is 0, it will append nothing more to the result
In the second recursive iteration: n=70304, depth=10, remainder=70304%10 = 4.
Since depth < n is still truthy, it will do a recursive call with 70304-4 and 10*10
And since remainder is 4, it will append a " + " and this 4 to the result
In the third recursive iteration: n=70300, depth=100, remainder=70300%100 = 0.
Since depth < n is still truthy, it will do a recursive call with 70300-0 and 100*10
And since remainder is 0, it will append nothing more to the result
In the fourth recursive iteration: n=70300, depth=1000, remainder=70300%1000 = 300.
Since depth < n is still truthy, it will do a recursive call with 70300-300 and 1000*10
And since remainder is 300, it will append a " + " and this 300 to the result
In the fifth recursive iteration: n=70000, depth=10000, remainder=70000%10000 = 0.
Since depth < n is still truthy, it will do a recursive call with 70000-0 and 10000*10
And since remainder is 0, it will append nothing more to the result
In the sixth recursive iteration: n=70000, depth=100000, remainder=70000%100000 = 70000.
Since now depth < n is falsey, it won't do any more recursive calls, but instead return the current n (which is 70000).
And since these were all recursive calls, we should actually look at it backwards for the result, so it will result in 70000 + 300 + 4.
So in general:
The depth < n if-check is to see when we are done with the recursive calls.
The g(n-remainder, depth*10) will remove the digits we've already output in a previous recursive iteration, and goes to the next 10k power in the next recursive iteration
The remainder != 0 if-check determines if the number we want to append was not a 0
public class Kata
{
public static String expandedForm(int num)
{
String outs = "";
for (int i = 10; i < num; i *= 10) {
int rem = num % i;
outs = (rem > 0) ? " + " + rem + outs : outs;
num -= rem;
}
outs = num + outs;
return outs;
}
}
package backup;
import java.util.Arrays;
public class FileOutput {
public static void main(String[] args){
String expForm = expandedForm(70304);
//System.out.println(expForm);
}
public static String expandedForm(int num)
{
String[] str = Integer.toString(num).split("");
String result = "";
for(int i = 0; i < str.length-1; i++) {
if(Integer.valueOf(str[i]) > 0) {
for(int j = i; j < str.length-1; j++) {
str[i] += '0';
}
}
}
result = Arrays.toString(str);
result = result.substring(1, result.length()-1).replace(",", " +");
System.out.println(result);
return result;
}
}
Output : 70000 + 0 + 300 + 0 + 4
Solution in most inner loop you need to add '0' to str[i] : str[i] += '0';
Then you need to replace "+ 0" from the resulted output.
for(int i = 0; i < str.length; i++) {
if(Integer.valueOf(str[i]) > 0) {
for(int j = 0; j < str.length - i - 1; j++) {
str[i] += '0';
}
}
}
I think the challenge of this problem is omitting 0(zero) and extra +(plus) while iterating throughout the number. String concat function can be used with condition as bellow:
public static String expandedForm(int num) {
String st = String.valueOf(num);
String finalResult = "";
for (int i = 0; i < st.length(); i++) {
String s = String.valueOf(st.charAt(i));
if (Integer.valueOf(s) > 0) {
for (int j = i; j < st.length() - 1; j++) {
s = s.concat("0");
}
if (i == st.length() - 1) {
finalResult = finalResult.concat(s);
} else {
finalResult = finalResult.concat(s + " + ");
}
}
}
return finalResult;
}
public static String expandedForm(int num)
{
String[] str = Integer.toString(num).split("");
String result = "";
String st="";
for(int i = 0; i < str.length-1; i++) {
if(Integer.valueOf(str[i]) > 0) {
for(int j = i; j < str.length-1; j++) {
str[i] += '0';
}
}
}
for(String s:str) {
st += s+" ";
}
result=st;
result = result.substring(0, result.length()-1).replace(" 0","").replace(" ", " + ");
System.out.println(result);
return result;
}
public static String expandedForm(int num)
{
int numberOfDigits =(int) Math.floor(Math.log10(num)+1);
String result="";
while(numberOfDigits-->0){
int divisor = (int)Math.pow(10,numberOfDigits);
int quotient = num/divisor;
num%=divisor;
int value = quotient * divisor;
if(value!=0)
result+=value+(numberOfDigits != 0 ?"+":"");
}
return result;
}
Try with this.
Find number of digits and iterate for every single digit.
Make a divisor of 10 power (number of digits -1) and divide the number to get quotient.
Take reminder for next iteration.
Multiply quotient and divisor and store in result if it value is not zero.
Simple Javascript Expanded Form of a number
Asked in interviews for beginners/Juniors
function expandedForm(n){
let temp = n;
let count=0;
while(temp>0){
console.log(((temp%10)*(10**count)));
count++;
temp = Math.floor(temp/10);
}
}
output will be like this:-
7
80
400
5000
10000
I'm making a program that accepts two decimal numbers and convert them into binary numbers, which are stored in integer arrays. Then I need to do multiplication using the two integer arrays. The result should also be a binary integer array (I need to validate that using a for loop). Then I convert them result to decimal number.
So far, I have the following code. My logic to convert the decimal number to binary works fine and vice verse. However, the binary result is always somehow smaller than the expected result. I have spent a lot of time on this, could you help me check what is wrong?
public class BinaryMultiplication {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num1 = scanner.nextInt();
int num2 = scanner.nextInt();
int[] binaryNum1 = toBinary(num1);
int[] binaryNum2 = toBinary(num2);
System.out.println("Expected result: " + num1 * num2);
System.out.println("Decimal number 1: " + toDecimal(binaryNum1));
System.out.println("Decimal number 2: " + toDecimal(binaryNum2));
int[] resultBinaries = new int[100];
for (int i = 0; i < resultBinaries.length; ++i) {
resultBinaries[i] = 0;
}
for (int i = 0; binaryNum1[i] != -1; ++i) {
for (int j = 0; binaryNum2[j] != -1; ++j) {
resultBinaries[i + j] += binaryNum1[i] * binaryNum2[j] % 2;
resultBinaries[i + j] %= 2;
}
}
resultBinaries[99] = -1;
for (int i = 0; resultBinaries[i] != -1; ++i) {
if (resultBinaries[i] > 1) {
System.out.println("The result is not a binary!!");
}
}
System.out.println("Actual decimal result: " + toDecimal(resultBinaries));
}
public static int toDecimal(int[] binaryNum) {
int result = 0;
int factor = 1;
for (int i = 0; binaryNum[i] != -1; ++i) {
result += binaryNum[i] * factor;
factor *= 2;
}
return result;
}
public static int[] toBinary(int num) {
int[] binaries = new int[100];
int index = 0;
while (num > 0) {
binaries[index++] = num % 2;
num /= 2;
}
binaries[index] = -1;
return binaries;
}
}
A sample input & output: ( the binary validation loop works fine)
45 67
Expected result: 3015
Decimal number 1: 45
Decimal number 2: 67
Actual decimal result: 2871
for (int i = 0; binaryNum1[i] != -1; ++i) {
for (int j = 0; binaryNum2[j] != -1; ++j) {
resultBinaries[i + j] += binaryNum1[i] * binaryNum2[j] % 2;
resultBinaries[i + j] %= 2;
}
}
What happens when resultBinaries[i + j] increases to 2? It's reduced to 0 and then resultBinaries[i + j + 1] should be increased with 1, but this isn't happening in the code as far as I can see.
I am working on an interview question which I was asked in which I was supposed to write a program to find the largest palindrome from product of two three digit numbers.
Here is the question
I came up with this brute force approach which starts from bottom.
public class LargestPalindromeQuestion {
public static void main(String[] args) {
int value = 0;
for (int i = 100; i <= 999; i++) {
for (int j = i; j <= 999; j++) {
int value1 = i * j;
if (isPalindrome(value1) && value < value1) {
value = value1;
}
}
}
System.out.println(value);
}
private static boolean isPalindrome(final int product) {
int p = product;
int reverse = 0;
while (p != 0) {
reverse *= 10;
reverse += p % 10;
p /= 10;
}
return reverse == product;
}
}
They asked me what are the optimizations I can do in this program? I mentioned that we can try pruning the search space and optimize checking step for each item in the search space but then I am confuse how would I make this work in my above solution?
What are the optimizations we can do in this program? Right now it is executing 810000 steps to find the largest palindrome.
What is the least number of steps we can execute to find the largest palindrome in two three digit numbers?
The program looks very good to me. I would make the i loop count from 999 down to 100, and I would only check j values that would actually give a larger product than the current maximum.
This program is able to finish surprisingly soon, at i == 952 to be precise. The mathematical reason for this is that once the solution 906609 (993 * 913) is found, it will no longer be possible to find a larger palindrome where the larger factor is less than the square-root of 906609, which is 952.160....
public static void main(String[] args) {
int value = 0;
for (int i = 999; i >= 100; i--) {
int r = value / i;
if (r >= i) {
System.out.println("We broke at i = " + i);
break;
}
for (int j = i; j > r; j--) {
int value1 = i * j;
if (isPalindrome(value1)) {
value = value1;
break;
}
}
}
System.out.println(value);
}
One pretty simple way of optimizing this would be to simply start with the highest 3-digit numbers instead of the smallest. Since the solution will most likely be closer to the pair (999 , 999) than to (100 , 100).
One useful mechanism to prune the search tree is to notice that the highest digit of the product a * b doesn't change often. E.g.
a = 111; b = 112 a*b = 12432
; b = 113 a*b = 12543
; b = 114 a*b = 12654
; ...
; b = 180 a*b = 19980
; b = 181 a*b = 20091 = (19980 + a)
Thus, for all the values in between (a = 111, a < b < 181), one already knows the MSB, which must equal to the LSB or (a % 10) * (b % 10) % 10 == MSB.
e.g.
LSB = 1 --> a % 10 == 1, b % 10 == 1
OR a % 10 == 3, b % 10 == 7
OR a % 10 == 7, b % 10 == 3
OR a % 10 == 9, b % 10 == 9
Most of the time there's either none, or just one candidate in set 'b' to be checked for any pair MSB, a % 10.
The least number of steps I could get to is 375. Consider multiplying the three-digit number, a1a2a3, by the three-digit number, b1b2b3:
JavaScript code:
var modHash = new Array(10);
var iterations = 0;
for (var i=1; i<10; i++){
modHash[i] = {0: [0]}
for (var j=1; j<10; j++){
iterations ++;
var r = i * j % 10;
if (modHash[i][r])
modHash[i][r].push(j);
else
modHash[i][r] = [j];
}
}
var highest = 0;
function multiples(x,y,carry,mod){
for (var i in modHash[x]){
var m = (10 + mod - i - carry) % 10;
if (modHash[y][m]){
for (var j in modHash[x][i]){
for (var k in modHash[y][m]){
iterations ++;
var palindrome = num(9,modHash[y][m][k],x,9,modHash[x][i][k],y);
if (x == 3 && mod == 0){
console.log(x + " * " + modHash[x][i][j] + " + "
+ y + " * " + modHash[y][m][k] + ": " + palindrome);
}
var str = String(palindrome);
if (str == str.split("").reverse().join("") && palindrome > highest){
highest = palindrome;
}
}
}
}
}
}
function num(a1,a2,a3,b1,b2,b3){
return (100*a1 + 10*a2 + a3)
* (100*b1 + 10*b2 + b3);
}
var a3b3s = [[7,7,4],[9,1,0],[3,3,0]];
for (var i in a3b3s){
for (var mod=0; mod<10; mod++){
var x = a3b3s[i][0],
y = a3b3s[i][1],
carry = a3b3s[i][2];
multiples(x,y,carry,mod);
}
}
console.log(highest);
console.log("iterations: " + iterations);
Output:
3 * 0 + 3 * 0: 815409
3 * 7 + 3 * 3: 907809
3 * 4 + 3 * 6: 908109
3 * 1 + 3 * 9: 906609
3 * 8 + 3 * 2: 907309
3 * 5 + 3 * 5: 908209
3 * 2 + 3 * 8: 907309
3 * 9 + 3 * 1: 906609
3 * 6 + 3 * 4: 908109
3 * 3 + 3 * 7: 907809
906609
iterations: 375
First optimize isPalindrome by seperating 6 digits as 3 digits. i.e. N = ABCDEF => a = ABC = N/1000, b = DEF = N%1000; Then reverse b and return a==reversed_b;
Secondly while producing palindromes loop through till max_palindrome_so_far/999 which is the minimum value that you would use. max_palindrome_so_far is initially equals N.
public class Solution {
public static boolean isPalindrome(int n){
int a = n/1000;
int b = n%1000;
int d, r = 0, i = 3;
while(i-- > 0){
d = b%10;
r = r*10 + d;
b = b/10;
}
if (a == r)
return true;
return false;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
int n = in.nextInt();
int r=0, m=n;
int i,j;
for(i = 999;i>=100;i--){
for(j = 999;j>=m/999;j--){
if (i*j < n && i*j > 100000 && isPalindrome(i*j)){
r = Math.max(i*j, r);
m = r;
}
}
}
// System.out.println(i + " * " + j + " = " + i*j);
System.out.println(r);
}
}
}
I wrote a function that validates credit cards. It usses the last 10 digits of the card number. The card number is stored as a String. I'm trying to figure out how to converts the last 10 digits of the card number into a array numbers. I found some code on stack overflow, but it usses string instad of String. So I get a error when I try to access the string as a arrow
Code:
int[] n = { 0, 0, 0, 8, 2, 9, 8, 7, 0, 1 };
boolean ValidCredt()
{
String strNum = "1230008298701";
int p = strNum.length() - 1;
int pt = 9;
// this is where I'm trying to convert the String into a arrow of
// numbers
for (int i = 0; i < 10; i++)
{
n[pt--] = strNum[p--] - '0'; // get a error for tryinmg to usr
// String as a array
}
// step 1 double every other digit
n[9] = n[9] + n[9];
n[7] = n[7] + n[7];
n[5] = n[5] + n[5];
n[3] = n[3] + n[3];
n[1] = n[1] + n[1];
// Your number is now “0-0-0-16-2-18-8-14-0-2.”
// step 3 add together 2 digy
for (int i = 0; i < n.length; i++)
{
if (n[i] > 9)
{
int low = n[i] % 10;
int hi = n[i] / 10;
n[i] = low + hi;
}
}
// Your number is now “0-0-0-7-2-9-8-5-0-2.”
// step 4
int sum = 0;
for (int i = 0; i < n.length; i++)
sum = sum + n[i];
// step 5
int step5 = sum * 9;
int step5b = 10 - sum % 10;
// step 6
int step6 = sum + step5 % 10;
if (step5 % 10 == 0)
return true;
return false;
}
I'm not sure why have you tried so complicated stuff, but I think this might be useful:
String ccNumber = "1234567890";
char[] characters = ccNumber.toCharArray();
int[] result = new int[characters.length];
int i = 0;
for (char c : characters) {
result[i++] = c - '0';
}
int[] result = new int[string.size()];
for(int i = 0; i < string.size(); i++){
result[i] = string.charAt(i) - '0';
}
In my project I have to deal with multiplication of big numbers ( greater then java.long ) stared in my own BigNumber class as int[]. Basically I need to implement something like this :
157 x
121 y
----
157 result1
314 + result2
157 + result3
------
18997 finalResult
But how do I implement it?
I thought about expanding result2,3 with zeros (3140, 15700) and adding them. But first I somehow need to navigate between each digit of y and multiply it by each digit of x.
Use the diagonal approach. Make an array, and multiply each digit by each other digit and fill in the numbers in each cell.
36 x 92
3 6
+-----+-----+
| 2 / | 5 / |
9 | / | / |
| / 7 | / 4 |
+-----+-----+
| 0 / | 1 / |
2 | / | / |
| / 6 | / 2 |
+-----+-----+
Add the numbers on each diagonal. Move from the least-significant digit (at the lower right) to the most (upper left).
2 2 (least-significant)
(6 + 1 + 4) = 11 (make this 1, and carry the 1 to the next digit) 1
(5 + 7 + 0 + 1(carried)) = 13 (make this 3, and carry the 1) 3
2 + 1(carried) = 3 3 (most-significant)
The answer's 3312.
Make a two-dimensional array of your digits. Fill the array with the multiplications of the single digits together.
Write some logic to scrape the diagonals as I did above.
This should work for arbitrarily large numbers (as long as you still have memory left).
Here's the code I had written. Basically same as manual multiplication. Pass the two big numbers as strings to this function, the result is returned as a string.
public String multiply(String num1, String num2){
int product, carry=0, sum=0;
String result = new String("");
String partial = new String("");
ArrayList<String> partialList = new ArrayList<String>();
/* computing partial products using this loop. */
for(int j=num2.length()-1 ; j>=0 ; j--) {
for(int i=num1.length()-1 ; i>=0 ; i--) {
product = Integer.parseInt((new Character(num1.charAt(i))).toString()) *
Integer.parseInt((new Character(num2.charAt(j))).toString()) + carry;
carry = product/10;
partial = Integer.toString(product%10) + partial;
}
if(carry != 0)
partial = Integer.toString(carry) + partial;
partialList.add(partial);
partial = "";
carry = 0;
}
/* appending zeroes incrementally */
for(int i=0 ; i<partialList.size() ; i++)
partialList.set(i, partialList.get(i) + (Long.toString( (long)java.lang.Math.pow(10.0,(double)i))).substring(1) );
/* getting the size of the largest partial product(last) */
int largestPartial = partialList.get(partialList.size()-1).length();
/* prefixing zeroes */
int zeroes;
for(int i=0 ; i<partialList.size() ; i++) {
zeroes = largestPartial - partialList.get(i).length();
if(zeroes >= 1)
partialList.set(i, (Long.toString( (long)java.lang.Math.pow(10.0,(double)zeroes))).substring(1) + partialList.get(i) );
}
/* to compute the result */
carry = 0;
for(int i=largestPartial-1 ; i>=0 ; i--) {
sum = 0;
for(int j=0 ; j<partialList.size() ; j++)
sum = sum + Integer.parseInt(new Character(partialList.get(j).charAt(i)).toString());
sum = sum + carry;
carry = sum/10;
result = Integer.toString(sum%10) + result;
}
if(carry != 0)
result = Integer.toString(carry) + result;
return result;
}
I would avoid the headaches of writing your own and just use the java.math.BigInteger class. It should have everything you need.
Separating out the carrying and the digit multiplication:
def carries(digitlist):
digitlist.reverse()
for idx,digit in enumerate(digitlist):
if digit>9:
newdigit = digit%10
carry = (digit-newdigit)/10
digitlist[idx] = newdigit
if idx+1 > len(digitlist)-1:
digitlist.append(carry)
else:
digitlist[idx+1] += carry
digitlist.reverse()
return True
def multiply(first,second):
digits = [0 for place in range(len(first)+len(second))]
for fid,fdig in enumerate(reversed(first)):
for sid,sdig in enumerate(reversed(second)):
offset = fid+sid
mult = fdig*sdig
digits[offset] += mult
digits.reverse()
carries(digits)
return digits
def prettify(digitlist):
return ''.join(list(`i` for i in digitlist))
Then we can call it:
a = [1,2,3,4,7,6,2]
b = [9,8,7,9]
mult = multiply(a,b)
print prettify(a)+"*"+prettify(b)
print "calc:",prettify(mult)
print "real:",int(prettify(a))*int(prettify(b))
Yields:
1234762*9879
calc: 12198213798
real: 12198213798
Of course the 10s in the carries function and the implicit decimal representation in prettify are the only thing requiring this to be base 10. Adding an argument could make this base n, so you could switch to base 1000 in order to reduce the numbers of blocks and speed up the calculation.
I have implemented this in C++. refer to this for logic...
#include <iostream>
#include <deque>
using namespace std;
void print_num(deque<int> &num) {
for(int i=0;i < num.size();i++) {
cout<<num[i];
}
cout<<endl;
}
deque<int> sum(deque<int> &oppA, deque<int> &oppB) {
if (oppA.size() == 0) return oppB;
if (oppB.size() == 0) return oppA;
deque<int> result;
unsigned int carry = 0;
deque<int>::reverse_iterator r_oppA = oppA.rbegin();
deque<int>::reverse_iterator r_oppB = oppB.rbegin();
while ((r_oppA != oppA.rend()) && (r_oppB != oppB.rend())) {
int tmp = *r_oppA + *r_oppB + carry;
result.push_front(tmp % 10);
carry = tmp / 10;
r_oppB++;
r_oppA++;
}
while (r_oppA != oppA.rend()) {
int tmp = *r_oppA + carry;
result.push_front(tmp % 10);
carry = tmp / 10;
r_oppA++;
}
while (r_oppB != oppB.rend()) {
int tmp = *r_oppB + carry;
result.push_front(tmp % 10);
carry = tmp / 10;
r_oppB++;
}
return result;
}
deque<int> multiply(deque<int>& multiplicand, deque<int>& multiplier) {
unsigned int carry = 0;
deque<int> result;
int deci_cnt = 0;
deque<int>::reverse_iterator r_multiplier = multiplier.rbegin();
deque<int> tmp_result;
while (r_multiplier != multiplier.rend()) {
for (int i=0; i<deci_cnt ;i++) {
tmp_result.push_front(0);
}
deque<int>::reverse_iterator r_multiplicand = multiplicand.rbegin();
while (r_multiplicand != multiplicand.rend()) {
int tmp = (*r_multiplicand) * (*r_multiplier) + carry;
tmp_result.push_front(tmp % 10);
carry = tmp / 10;
r_multiplicand++;
}
if (carry != 0) {
tmp_result.push_front(carry);
carry = 0;
}
result = sum(result, tmp_result);
deci_cnt++;
tmp_result.clear();
r_multiplier++;
}
return result;
}
deque<int> int_to_deque(unsigned long num) {
deque<int> result;
if (num == 0) {
result.push_front(0);
}
while (num > 0) {
result.push_front(num % 10);
num = num / 10;
}
return result;
}
int main() {
deque<int> num1 = int_to_deque(18446744073709551615ULL);
deque<int> num2 = int_to_deque(18446744073709551615ULL);
deque<int> result = multiply(num1, num2);
print_num(result);
return 0;
}
Output: 340282366920928463426481119284349108225
You're going to have to treat each int in the array as a single "digit". Instead of using base 10 where each digit goes from 0 to 9, you'll have to use base 2^32 = 4294967296, where every digit goes from 0 to 4294967295.
I would first implement addition, as your algorithm for multiplication might use addition as an auxiliary.
As this is for homework I'll give a few hints.
You could approach it the same way you show your example, using strings to hold numbers of any length and implementing:
add one number to another
multiply as your example by appending zeroes and calling the addition method per step (so for multiply with 20, append the "0" and addd that number twice
The addition method you can build by retrieving the char[] from the strings, allocate a result char[] that is 1 longer than the longest and add like you would do on paper from the end back to the start of both arrays.
The end result will not be the best performing solution, but it it easy to show it is correct and will handle any length numbers (as long they will fit a Java string.)
Update
Ok, if you solved adding two numbers, you could:
implement multiplication by 10
implement multiplication by repeated addition like in your example
or:
implement multiplication by 2 (left shift)
implement a binary multiplication via the same concept, only this time x 2 and add once
to illustrate the latter,
13
5 x
----
13 x 1
26 x 0
52 x 1
---- +
65
note that the 1 0 1 are the bits in the number (5) you multiply with and 26 = 13 x 2, 52 = 26 x 2. Your get the idea :-)
did it my own way :
int bigger = t1.length;
int smaller = t2.length;
int resultLength = bigger + smaller;
int []resultTemp = new int[resultLength];
int []result = new int[bigger + smaller];
int []temporary = new int[resultLength+1];
int z = resultLength-1;
int zet = z;
int step = 0;
int carry = 0;
int modulo = 0;
for(int i=smaller-1; i>=0; i--){
for(int k = bigger-1; k>= -1; k--){
if(k == -1 && carry != 0 ){
resultTemp[z] = carry;
carry = 0;
break;
}
else if(k == -1 && carry == 0){
resultTemp[z] = 0;
break;
}
resultTemp[z] = carry + t1[k]*t2[i];
carry = 0;
if( resultTemp[z] > 9 ){
modulo = resultTemp[z] % 10;
carry = resultTemp[z]/10;
resultTemp[z] = modulo;
}
else{
resultTemp[z] = resultTemp[z];
}
z--;
}
temporary = add(resultTemp, result);
result = copyArray(temporary);
resultTemp = clear(resultTemp);
z = zet;
step++;
z = z - step;
}
then I check the sign.
Since this is homework... Are you sure using an int array is your best shot?
I tried to implement something similar a year ago for performance in a research
project, and we ended up going with concatenated primitives..
Using this you can take advantage of what's already there, and "only" have to worry about overflows near the ends.. This might prove to be fairly simple when you implement your multiplication with <<'s (bit shift lefts) and additions..
Now if you want a real challenge try to implement a modulo... ;)
You can check the below solution which teaches us both multiplication and addition of bigger numbers. Please comment if it can be improved.
public static void main(String args[]) {
String s1 = "123666666666666666666666666666666666666666666666669999999999999999999999999666666666666666666666666666666666666666666666666666666666666666666";
String s2 = "45688888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888";
System.out.println(multiply(s1, s2));
}
private static String multiply(String s1, String s2) {
int[] firstArray = convert(s1);
int[] secondArray = convert(s2);
//System.out.println(Arrays.toString(firstArray));
//System.out.println(Arrays.toString(secondArray));
// pass the arrays and get the array which is holding the individual
// rows while we multiply using pen and paper
String[] result = doMultiply(firstArray, secondArray);
//System.out.println(Arrays.toString(result));
// Now we are almost done lets format them as we like
result = format(result);
//System.out.println(Arrays.toString(result));
//Add elements now and we are done
String sum="0";
for(String s:result){
sum=add(sum,s);
}
return sum;
}
private static String[] doMultiply(int[] firstArray, int[] secondArray) {
String[] temp = new String[secondArray.length];
for (int i = secondArray.length - 1; i >= 0; i--) {
int result = 0;
int carry = 0;
int rem = 0;
temp[secondArray.length - 1 - i] = "";
for (int j = firstArray.length - 1; j >= 0; j--) {
result = (secondArray[i] * firstArray[j]) + carry;
carry = result / 10;
rem = result % 10;
temp[secondArray.length - 1 - i] = rem
+ temp[secondArray.length - 1 - i];
}
// if the last carry remains in the last digit
if (carry > 0)
temp[secondArray.length - 1 - i] = carry
+ temp[secondArray.length - 1 - i];
}
return temp;
}
public static int[] convert(String str) {
int[] arr = new int[str.length()];
for (int i = 0; i < str.length(); i++) {
arr[i] = Character.digit(str.charAt(i), 10);
}
return arr;
}
private static String[] format(String[] result) {
for (int i = 0; i < result.length; i++) {
int j = 0;
while (j < i) {
result[i] += "0";
j++;
}
}
return result;
}
public static String add(String num1, String num2) {
//System.out.println("First Number :" + num1);
//System.out.println("Second Number :" + num2);
int max = num1.length() > num2.length() ? num1.length() : num2.length();
int[] numArr1 = new int[max];
int[] numArr2 = new int[max];
for (int i = 0; i < num1.length(); i++) {
numArr1[i] = Integer.parseInt(""
+ num1.charAt(num1.length() - 1 - i));
}
for (int i = 0; i < num2.length(); i++) {
numArr2[i] = Integer.parseInt(""
+ num2.charAt(num2.length() - 1 - i));
}
int carry = 0;
int[] sumArr = new int[max + 1];
for (int k = 0; k < max; k++) {
int tempsum = numArr1[k] + numArr2[k] + carry;
sumArr[k] = tempsum % 10;
carry = 0;
if (tempsum >= 10) {
carry = 1;
}
}
sumArr[max] = carry;
/* System.out.println("Sum :"
+ new StringBuffer(Arrays.toString(sumArr)).reverse()
.toString().replaceAll(",", "").replace("[", "")
.replace("]", "").replace(" ", ""));*/
return new StringBuffer(Arrays.toString(sumArr)).reverse().toString()
.replaceAll(",", "").replace("[", "").replace("]", "")
.replace(" ", "");
}
I think this will help you
import java.util.ArrayList;
import java.util.List;
public class Multiply {
static int len;
public static void main(String[] args) {
System.out.println(multiply("123456789012345678901","123456789012345678901");
}
private static ArrayList<Integer> addTheList(List<ArrayList<Integer>> myList) {
ArrayList<Integer> result=new ArrayList<>();
for(int i=0;i<len;i++)
{
result.add(0);
}
int index=0;
for(int i=0;i<myList.size();i++)
{
ArrayList<Integer> a=new ArrayList<>(myList.get(index));
ArrayList<Integer> b=new ArrayList<>(myList.get(index+1));
for (int j = 0; j < a.size()||j < b.size(); i++) {
result.add(a.get(i) + b.get(i));
}
}
return result;
}
private static ArrayList<Integer> multiply(ArrayList<Integer> list1, Integer integer) {
ArrayList<Integer> result=new ArrayList<>();
int prvs=0;
for(int i=0;i<list1.size();i++)
{
int sum=(list1.get(i)*integer)+prvs;
System.out.println(sum);
int r=sum/10;
int m=sum%10;
if(!(r>0))
{
result.add(sum);
}
else
{
result.add(m);
prvs=r;
}
if(!(i==(list1.size()-1)))
{
prvs=0;
}
}
if(!(prvs==0))
{
result.add(prvs);
}
return result;
}
private static ArrayList<Integer> changeToNumber(String str1) {
ArrayList<Integer> list1=new ArrayList<>();
for(int i=0;i<str1.length();i++)
{
list1.add(Character.getNumericValue(str1.charAt(i)));
}
return list1;
}
public static String multiply(String num1, String num2) {
String n1 = new StringBuilder(num1).reverse().toString();
String n2 = new StringBuilder(num2).reverse().toString();
int[] d = new int[num1.length()+num2.length()];
//multiply each digit and sum at the corresponding positions
for(int i=0; i<n1.length(); i++){
for(int j=0; j<n2.length(); j++){
d[i+j] += (n1.charAt(i)-'0') * (n2.charAt(j)-'0');
}
}
StringBuilder sb = new StringBuilder();
//calculate each digit
for(int i=0; i<d.length; i++){
int mod = d[i]%10;
int carry = d[i]/10;
if(i+1<d.length){
d[i+1] += carry;
}
sb.insert(0, mod);
}
//remove front 0's
while(sb.charAt(0) == '0' && sb.length()> 1){
sb.deleteCharAt(0);
}
return sb.toString();
}
}