2014-09-04 2 views
0

목표는 두 개의 거대한 정수를 읽고 더하거나 뺄셈 한 다음 40 개의 긴 정수 배열로 다시 곱하는 동시에 초기 두 정수, equalTo, notEqualTo 등을 비교하는 것입니다. 그것의 대부분은 완료하지만 나는 몇 점에 붙어 있습니다. 내 isGreaterThan 메서드는 예를 들어 거대한 정수 1 = 100 및 거대한 정수 2 = -100과 같이 반대 위치를 반환합니다. 이 메서드는 거짓말을하고 거대한 정수 1 isLessThan 거대한 정수 2라고 말합니다. 다음 부분은 곱셈입니다. 현재로서는 정수를 곱하여 11 개의 원소가 아닌 새로운 정수를 얻을 수 있습니다. 어떤 미지의 이유로 나에게 커다란 것은 오산을 초래할 것입니다. 루프에 대해 여러 번 제안했지만 그게 도움이 될지 모르겠다. 나의 마지막 문제는 어떤 연산의 결과가 0 일 때마다이다. 예를 들어 100 + (-100), add/substract/multiply 메소드가 0을 반환하지 않는다. 아래는 현재 코드이다.배열 비교 및 ​​곱하기

import java.util.Scanner; 
import java.util.Arrays; 

// Class that prompts the user to enter two HugeIntegers 
// then compares those integers and performs addition, subtraction, 
// and multiplication on those two HugeIntegers 
public class HugeInteger { 
    private static final int NUM_DIGITS = 40; 
    private int digits[] = new int[NUM_DIGITS]; 
    private boolean positive; 

    // Constructor 
    public HugeInteger (String num){ 
     String parts [] = num.split(" "); 
     digits = new int[parts.length]; 
     for(int n = 0; n < parts.length; n++) { 
      digits[n] = Integer.parseInt(parts[n]); 
     } 
    } 

    // Finds first non-zero position for first HugeInteger 
    public int findFirstNonZeroPosition(){ 
     int position = NUM_DIGITS-1; 
     for (int i = 0; i < digits.length; i++){ 
      if (digits[i] > 0){ 
       position = i; 
       break; 
      } 
     } 
     return position; 
    } 

    // Determines if h1 isEqualTo h2 
    public boolean isEqualTo(HugeInteger hi){ 
     if(Arrays.equals(this.digits, hi.digits)){ 
      return true; 
     }else { 
      return false; 
     } 
    } 

    // Determines if hi isGreaterThan h2 
    public boolean isGreaterThan(HugeInteger hi){ 
     // different signs 
     if (this.positive && (!hi.positive)){ 
      return true; 
     } 
     else if (!this.positive && hi.positive){ 
      return false; 
     } 

     // same sign 
     else { 

      // first number’s length is less than second number’s length 
      if (findFirstNonZeroPosition() > hi.findFirstNonZeroPosition()) { 
       if (positive) 
        return false; 
       else 
        return true; 
      } 

      // first number’s length is larger than that of second number 
      else if (findFirstNonZeroPosition() < hi.findFirstNonZeroPosition()) { 
       if (positive) 
        return true; 
       else 
        return false; 
      } 

      // two numbers have same length 
      else { 
       for (int i = 0; i < digits.length; i++) { 
        if (this.digits[i] > hi.digits[i]) 
         if (positive) 
          return true; 
         else 
          return false; 
       } 
       if (positive) 
        return false; 
       else 
        return true; 
      } 
     } 
    } 

    // Determines if h1 isNotEqualTo h2 
    public boolean isNotEqualTo(HugeInteger hi){ 
     if(Arrays.equals(this.digits, hi.digits)){ 
      return false; 
     }else { 
      return true; 
     } 
    } 

    // Determines if h1 isLessThan h2 
    public boolean isLessThan(HugeInteger hi){ 
     return !(isGreaterThan(hi) || isEqualTo(hi)); 
    } 

    // Determines if h1 isGreaterThanOrEqualTo h2 
    public boolean isGreaterThanOrEqualTo(HugeInteger hi){ 
     return !isLessThan(hi); 
    } 

    // Determines if h1 isLessThanOrEqualTo h2 
    public boolean isLessThanOrEqualTo(HugeInteger hi){ 
     return !isGreaterThan(hi); 
    } 

    // instance variables are digits, NUM_DIGITS, positive 
    // addArrayDigits and subtractArrayDigits 
    // Determines how to add h1 and h2 
    public void add(HugeInteger hi){ 
     if(positive!=hi.positive){ 
      if(this.positive){ 
       // "this" is positive, hi is negative 
       hi.negate(); // negate hi temporarily 

       if(this.isGreaterThan(hi)){ 
        // |this| > |hi| 
        this.digits = subtractArrayDigits(this.digits, hi.digits); 
       }else{ 
        // |this| <= |hi| 
        this.digits = subtractArrayDigits(hi.digits, this.digits); 
        // negate the "this" 
        negate(); 
       } 
       hi.negate(); // restore hi's sign 
      }else{ 
       // "this" is negative, hi is positive 

      } 
     }else{ 
      // same sign :) 
      digits = addArrayDigits(this.digits, hi.digits); 
     } 
    } 

    // instance variables are digits, NUM_DIGITS, positive 
    // addArrayDigits and subtractArrayDigits 
    // Determines how to subtract h1 and h2 
    public void subtract(HugeInteger hi){ 
     if(positive!=hi.positive){ 
      if(this.positive){ 
       // "this" is positive, hi is negative 
       hi.negate(); // negate hi temporarily 

       if(this.isGreaterThan(hi)){ 
        // |this| > |hi| 
        this.digits = addArrayDigits(this.digits, hi.digits); 
       }else{ 
        // |this| <= |hi| 
        this.digits = addArrayDigits(hi.digits, this.digits); 
        // negate the "this" 
        negate(); 
       } 
       hi.negate(); // restore hi's sign 
      }else{ 
       // "this" is negative, hi is positive 
      } 
     }else{ 
      // same sign :) 
      digits = subtractArrayDigits(this.digits, hi.digits); 
     } 
    } 

    // Multiplies h1 and h2 
    public void multiply(HugeInteger hi){ 
     for (int i = 0; i < digits.length; ++i) { 
      digits[i] = this.digits[i] * hi.digits[i]; 
     } 
    } 

    // Flips the sign 
    public void negate(){ 
     positive =! positive; 
    } 

    // Determines if an element is zero 
    public boolean isZero(){ 
     for(int i = 0; i < digits.length; i++) 
     if(digits[i]!= 0) 
      return false; 
     return true; 
    } 

    // Puts HugeInteger into a String in LSD format 
    public String toString() { 
     String str = ""; 
     int i; 
     for(i = digits.length -1; i >= 0; i--) { 
      if(digits[i] != 0) 
      break; 
     } 
     for(int j = i; j >= 0; j--) { 
      str = digits[j] + str; 
     } 
     return str; 
    } 

    // Subtracts h2 from h1 
    private static int[] subtractArrayDigits(int[] array1, int[] array2){ 
     for (int i = 0; i < array1.length; ++i) { 
      array1[i] = array1[i] - array2[i]; 
     } 
     return array1; 
    } 

    // Adds h2 to h1 
    private static int[] addArrayDigits(int[] array1, int[] array2){ 
     //int i = 0; 
     for (int i = 0; i < array1.length; ++i) { 
      array1[i] = array1[i] + array2[i]; 
     } 
     return array1; 
    } 

    // Main method 
    public static void main(String args[]){ 
     HugeInteger h1, h2; 
     String num; 
     Scanner scan=new Scanner(System.in); 

     System.out.print("Please enter the first huge integer (h1): "); 
     num=scan.nextLine(); 
     h1=new HugeInteger(num); 

     System.out.print("Please enter the second huge integer (h2): "); 
     num=scan.nextLine(); 
     h2=new HugeInteger(num); 

     if(h1.isEqualTo(h2)){ 
      System.out.println("h1 is equal to h2."); 
     } 
     if(h1.isNotEqualTo(h2)){ 
      System.out.println("h1 is not equal to h2."); 
     } 
     if(h1.isGreaterThan(h2)){ 
      System.out.println("h1 is greater than h2."); 
     } 
     if(h1.isLessThan(h2)){ 
      System.out.println("h1 is less than to h2."); 
     } 
     if(h1.isGreaterThanOrEqualTo(h2)){ 
      System.out.println("h1 is greater than or equal to h2."); 
     } 
     if(h1.isLessThanOrEqualTo(h2)){ 
      System.out.println("h1 is less than or equal to h2."); 
     } 

     h1.add(h2); 
     System.out.printf("h1 + h2 = %s\n",h1); 
     h1.subtract(h2); 
     h1.subtract(h2); 
     System.out.printf("h1 - h2 = %s\n",h1); 
     h1.add(h2); 
     h1.multiply(h2); 
     System.out.printf("h1 * h2 = %s\n",h1); 
    } 
} 

답변

1

코드에 많은 문제가 있습니다.

가장 중요한 것은 거대한 값을 나타내는 내부 형식이 (코드 분석을 제외하고) 문서화되지 않았으며 일관성이없는 것처럼 보입니다. 그것은 어떤 형태의 sign/magnitude로 보이지만, 숫자는 어느 순서로 나타 납니까? 그것은 실제로 매우 중요합니다.

대부분의 경우 숫자 배열이 인덱스 0에서 최하위 숫자를 사용하여 가장 중요도가 높은 숫자에서 더 간단하게 실행되지만 숫자가 쓰여지는 방식과 반대입니다. (적어도 영어 로케일). 또한 최상위에서 최하위까지 실행될 수도 있지만,이 경우 최하위 숫자에 대한 유일한 합리적인 인덱스는 MAX_DIGITS - 1입니다. 귀하의 생성자에서, 당신은 숫자 배열의 중간에있는 임의의 지점에서 가장 중요한 자리와 함께, 가장 중요한 숫자에서 실행되는 숫자가 있다고 생각합니다. 내 생각에 당신은 을 다른 방법으로 생각합니다.

두 번째로 생성자는 positive 필드를 설정하지 않습니다. (실제로는 음수를 전혀 확인하지 않습니다.)

세 번째로 add()subtract() 메서드는 일시적으로도 인수를 수정해서는 안됩니다. 수정이 메서드의 목적의 일부가 아니라면 매우 나쁜 형식이며 불필요합니다.

넷째, 일부 부호 조합의 경우 add()subtract() 메서드는 아무 것도 수행하지 않습니다.

하지만 왜 산수 계산법이 잘못된 결과를 산출하는지에 대해 관심이 많았습니다. 내가 어느 자리가 각각의 거대 함이 가장 적다는 것을 알지 않으면 절대 산술을 제대로 할 수 없다는 말로 시작하자. 실제 알고리즘에 관해서는 기본적으로 종이에서 십진법 연산을 수행하는 것과 동일한 프로 시저를 구현해야합니다. 매우 중요하게도, 필요한 경우 한 자리에서 다음 자리로의 이동을 무시하거나 (빼기의 경우 더 중요한 곳에서 빌리는) 일은해서는 안됩니다. 귀하의 코드는 그렇게하지 않습니다.

산술 결과의 피연산자와 다른 숫자가 아닌 숫자가 다를 수 있습니다. 특히, N -digit 수만큼 m -digit 수의 곱셈은 (N +미터) -digit 수까지 생산할 수있다. 추가에는 하나의 추가 숫자가 필요할 수 있습니다. 물론, 빼기는 중요한 0이 아닌 자릿수를 줄일 수 있습니다.

+0

나는 positive = true를 추가 한 후; 생성자에게 내 모든 비교 논리는 잘 작동했습니다. 작동하지 않는 유일한 것은 거대한 정수의 곱셈과 0을 나타내는 0과 같은 연산 결과를 얻는 것입니다. 당신이 지적한 바에 의하면, 피연산자가 아마 배열의 중간에있을 것이기 때문에 이것이 틀렸다고 가정하고 있습니다. 어떻게 잘못했는지 알고 싶다면 배열의 오른쪽에 LSD를 맞추려면 어떻게해야합니까? –

+0

산술적으로 LSD가 인덱스 0에 있다고 가정하는 것처럼, 나는 그런 식으로 남겨 둘 것을 권한다. 숫자에 값을 할당 할 때는'digits [n] = Integer.parseInt (parts [part.length - n - 1])'을 사용하십시오. –

+0

산술 연산이 현재 작동하는 것으로 보인다면, 테스트 할 숫자가 int가 수용 할 수있는 값 범위와 비교하여 작기 때문일 수 있습니다. 두 개의 단일 (거대한) 숫자 2000000000과 2000000000을 추가해보십시오.'multiply()'메소드가 더 나쁩니다. 숫자 값을 고려하기 전에 두 피연산자가 둘 이상 (거대한) 숫자를 가질 때 실패합니다. 1 1 (== 2147483649 10 진수)에 2를 곱하거나 1을 덧셈 해보십시오. –