Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package model;
- import java.util.AbstractMap;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- public class BigNumber {
- private String numberAsString = "";
- public BigNumber(String numberAsString) {
- for (char digit : numberAsString.toCharArray()) {
- if (digit < '0' || digit > '9')
- throw new NumberFormatException("Given string can't be converted to a number");
- }
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(numberAsString);
- this.numberAsString = stringBuilder.reverse().toString();
- }
- public BigNumber(int length) {
- StringBuilder stringBuilder = new StringBuilder();
- for(int i = 0; i < length; i++)
- stringBuilder.append('0');
- numberAsString = stringBuilder.toString();
- }
- public String get() {
- numberAsString = numberAsString.replaceFirst("^0+(?!$)", "");
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(numberAsString);
- return stringBuilder.reverse().toString();
- }
- public int getLength() { return numberAsString.length(); }
- public void addDigit(int digit) {
- numberAsString = digit + numberAsString;
- }
- public void addDigit(char digit) {
- numberAsString = digit + numberAsString;
- }
- public BigNumber sumSequential(BigNumber otherBigNumber) {
- int aLength = getLength();
- int bLength = otherBigNumber.getLength();
- int maxLength = Math.max(aLength, bLength);
- int minLength = Math.min(aLength, bLength);
- BigNumber result = new BigNumber(maxLength + 1);
- int carry = 0;
- for (int digitIndex = 0; digitIndex < minLength; digitIndex++) {
- int aCurrentDigit = numberAsString.charAt(digitIndex) - '0';
- int bCurrentDigit = otherBigNumber.numberAsString.charAt(digitIndex) - '0';
- int sumOfDigits = aCurrentDigit + bCurrentDigit + carry;
- carry = sumOfDigits / 10;
- int resultingDigit = sumOfDigits % 10;
- result.numberAsString += resultingDigit;
- }
- if (aLength > minLength) {
- for(int digitIndex = minLength; digitIndex < maxLength; digitIndex++) {
- int currentDigit = numberAsString.charAt(digitIndex) - '0';
- int sumOfDigits = currentDigit + carry;
- carry = sumOfDigits > 9 ? 1 : 0;
- int resultingDigit = sumOfDigits % 10;
- result.numberAsString += resultingDigit;
- }
- if (carry > 0)
- result.numberAsString += carry;
- }
- else if (bLength > minLength) {
- for(int digitIndex = minLength; digitIndex < maxLength; digitIndex++) {
- int currentDigit = otherBigNumber.numberAsString.charAt(digitIndex) - '0';
- int sumOfDigits = currentDigit + carry;
- carry = sumOfDigits > 9 ? 1 : 0;
- int resultingDigit = sumOfDigits % 10;
- result.numberAsString += resultingDigit;
- }
- if (carry > 0)
- result.numberAsString += carry;
- }
- else if (carry > 0)
- result.numberAsString += carry;
- return result;
- }
- public static BigNumber sumSequential(BigNumber first, BigNumber second) {
- return first.sumSequential(second);
- }
- class ThreadedBigNumber extends Thread {
- private String partOfFirstNumber, partOfSecondNumber;
- private String result = "";
- private int carry;
- ThreadedBigNumber(String partOfFirstNumber, String partOfSecondNumber) {
- this.partOfFirstNumber = partOfFirstNumber;
- this.partOfSecondNumber = partOfSecondNumber;
- }
- public String getResult() {
- return result;
- }
- public int getCarry() {
- return carry;
- }
- @Override
- public void run() {
- int aLength = partOfFirstNumber.length();
- carry = 0;
- for (int digitIndex = 0; digitIndex < aLength; digitIndex++) {
- int aCurrentDigit = partOfFirstNumber.charAt(digitIndex) - '0';
- int bCurrentDigit = partOfSecondNumber.charAt(digitIndex) - '0';
- int sumOfDigits = aCurrentDigit + bCurrentDigit + carry;
- carry = sumOfDigits / 10;
- int resultingDigit = sumOfDigits % 10;
- result += resultingDigit;
- }
- }
- }
- public BigNumber sumMultiThreaded(BigNumber otherBigNumber) throws InterruptedException {
- return sumMultiThreaded(otherBigNumber, 4);
- }
- public BigNumber sumMultiThreaded(BigNumber otherBigNumber, int THREAD_COUNT) throws InterruptedException {
- //adding 0 to make both numbers equal in size
- int smallestLength = Math.min(getLength(), otherBigNumber.getLength());
- if (getLength() == smallestLength) {
- while (getLength() < otherBigNumber.getLength())
- numberAsString += '0';
- }
- else {
- while (otherBigNumber.getLength() < getLength())
- otherBigNumber.numberAsString += '0';
- }
- int actualLength = getLength();
- if (THREAD_COUNT > actualLength)
- THREAD_COUNT = actualLength;
- //holding copies of the numbers to be able to remove stuff
- String number1 = numberAsString;
- String number2 = otherBigNumber.numberAsString;
- ArrayList<ThreadedBigNumber> listOfThreads = new ArrayList<>();
- //splitting the numbers across THREAD_COUNT buckets
- for (int THREAD_INDEX = 0; THREAD_INDEX < THREAD_COUNT; THREAD_INDEX++) {
- //how many digits are there gonna be in the bucket
- int digitCountForBucket = (actualLength * THREAD_INDEX + actualLength) / THREAD_COUNT - (actualLength * THREAD_INDEX) / THREAD_COUNT;
- //getting the substrings from the numbers and then deleting them
- String subStrOfNumber1 = number1.substring(0, digitCountForBucket);
- String subStrOfNumber2 = number2.substring(0, digitCountForBucket);
- number1 = number1.substring(digitCountForBucket);
- number2 = number2.substring(digitCountForBucket);
- System.out.println("[*]Starting thread " + THREAD_INDEX + " to compute the sum of " + subStrOfNumber1 + " and " + subStrOfNumber2);
- ThreadedBigNumber threadedBigNumber = new ThreadedBigNumber(subStrOfNumber1, subStrOfNumber2);
- listOfThreads.add(threadedBigNumber);
- threadedBigNumber.start();
- }
- int carry = 0;
- StringBuilder stringBuilder = new StringBuilder();
- for (int THREAD_INDEX = 0; THREAD_INDEX < THREAD_COUNT; THREAD_INDEX++) {
- listOfThreads.get(THREAD_INDEX).join();
- String resultOfThread = listOfThreads.get(THREAD_INDEX).getResult();
- int carryForNextPart = listOfThreads.get(THREAD_INDEX).getCarry();
- if (carry > 0) {
- Map.Entry<String, Integer> ret = addCarryToNumber(resultOfThread);
- resultOfThread = ret.getKey();
- carryForNextPart = carryForNextPart | ret.getValue();
- }
- stringBuilder.append(resultOfThread);
- carry = carryForNextPart;
- }
- if (carry > 0)
- stringBuilder.append('1');
- return new BigNumber(stringBuilder.reverse().toString());
- }
- private Map.Entry<String, Integer> addCarryToNumber(String number) {
- int carry = 1;
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(number);
- for(int digitIndex = 0; digitIndex < number.length(); digitIndex++) {
- int digit = number.charAt(digitIndex) - '0';
- int newDigit = (digit + 1) % 10;
- stringBuilder.setCharAt(digitIndex, Character.forDigit(newDigit, 10));
- //if we stopped having a carry in the number, then no need to continue adding
- if (digit + 1 <= 9) {
- carry = 0;
- break;
- }
- }
- number = stringBuilder.toString();
- return new AbstractMap.SimpleEntry<>(number, carry);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement