Java中的大整数算法 - 家庭作业

时间:2011-12-01 00:01:26

标签: java math arbitrary-precision

所以这是一个家庭作业,我一直在做约10个小时。我想知道一些提示,看看我哪里出错了。所以我的任务是基本上为大整数做一个计算器,我的教授提供了骨架。他要求我们写的函数是减法,除法,乘法,取幂(x ^ n)和一个小函数。我很确定我的LessThan和multiply函数正常工作,但也许不行,反正我的工作在下面,我会在之后描述我的问题:

public class Calc {

//
// main
//
// Parses the command-line arguments as an integer
// operation, packages the operands as digit arrays,
// calls the appropriate calculator function, and 
// then outputs the result.
//
public static void main(String[] args) {
if (args.length == 3) {
    int[] input1 = construct(args[0]);
    int[] input2 = construct(args[2]);
    if (args[1].equals("plus")) {
    int[] result = plus(input1,input2);
    putln(result);
    } else if (args[1].equals("minus")) {
    int[] result = minus(input1,input2);
    putln(result);
    } else if (args[1].equals("times")) {
    int[] result = times(input1,input2);
    putln(result);
    } else if (args[1].equals("div")) {
    int[] result = div(input1,input2);
    putln(result);
    } else if (args[1].equals("power")) {
    int[] result = power(input1,input2);
    putln(result);
    } else if (args[1].equals("less")) {
    boolean result = lessThan(input1,input2);
    TextIO.putln(result);
    } else if (args[1].equals("equal")) {
    boolean result = equal(input1,input2);
    TextIO.putln(result);
    } else {
    TextIO.putln("Invalid binary operation.  Try using +, -, +, /, ^, <, or =.");
    }
} else if (args.length == 2) {
    int[] input = construct(args[0]);
    // it must be a unary operation
    if (args[1].equals("!")) {
    int[] result = factorial(input);
    TextIO.putln(result);
    } else {
    TextIO.putln("Expected factorial operation!");
    }
} else {
    TextIO.putln("Invalid input.  Try either a binary operation or factorial.");
}
}


//
// plus
//
// Computes the sum of two digit arrays,
// represented as a digit array.
//
public static int[] plus(int[] a, int[] b) {

// Determine the result's maximum length.
//
int alen, blen, len;
alen = length(a);
blen = length(b);
if (alen > blen) {
    len = alen + 1;
} else {
    len = blen + 1;
}

// Allocate an array of digits with that length.
//
int[] c = new int[len];

// Compute the sum of the digits, working from
// least to most significant.
//
int carry = 0;
for (int i = 0; i < len; i = i+1) {
    int sum = carry;
    if (i < alen) {
    sum = sum + a[i];
    }
    if (i < blen) {
    sum = sum + b[i];
    }
    c[i] = sum % 10;
    carry = sum / 10;
}

// Trim off the leading 0s.
//
return trim(c);
}

// INCOMPLETE
//
// minus
//
// Computes the difference of two digit arrays,
// represented as a digit array.
//
// You can assume that the first operand is 
// larger than the second one.
//
public static int[] minus(int[] a, int[] b) {
    if(equal(a,b))
    {
        int [] zero = new int [1];
                zero[0] = 0;
        return zero;
    }
    else{

    int c = 0;

    int lb = length(b);
    while(lb > c)
        {
            b[c] = (b[c]) * (-1);
            c++;
        }
    return plus(a,b);
    }
}


// INCOMPLETE
//
// times
//
// Computes the product of two digit arrays,
// represented as a digit array.
//
// HINT: use repeated addition.  You might need
//       to write lessThan first.
//
// BONUS: perform this using the schoolbook 
//        method.
//
public static int[] times(int[] a, int[] b) {
    int len;
        if(length(a) > length(b))
            len = length(a) + 1;
        else
            len = length(b) + 1;
        int[] c = new int[len];
        int[]counterArray;
        if(lessThan(a,b))
        {
            counterArray = new int[length(b)];
            counterArray[length(b)-1] = 1;
        }
        else
        {
            counterArray = new int[length(a)];
            counterArray[length(a)-1] = 1;
        }

        int[] counterTwo = new int[1];
        counterTwo[0] = 1;
        while(lessThan(counterArray,a))
            {
        c = plus(c,b);
        counterArray = plus(counterArray, counterTwo);
            }
        return plus(c,b);
}

// INCOMPLETE
//
// div
//
// Computes the quotient of two digit arrays,
// represented as a digit array.
//
public static int[] div(int[] a, int[] b) {
    int[] counter = zero();
    boolean value = true;
    if(lessThan(a,b))
        return zero();
    else {
        while(value)
        {
            a = minus(a,b);
            counter = plus(counter,one());
            if(lessThan(b,a))
                value = false;

        }
        return counter;
    }

/**boolean checker = false;
int[] c = new int[length(a)];
for(int i = 0; i < length(a); i++)
{
    c[i] = 0;
}
int counter = 0;
while (!checker)
{
    if(equal(a,c))
    {
        checker = true;

    }
    else if(lessThan(a,c))
    {
        checker = true;
    }
    else if (lessThan(c,a))
    {
        c = plus(c,b);
        counter++;
    }
}
return construct("" + (counter));*/
}

// 
// factorial
//
// Computes the factorial of a digit array,
// as a digit array.
//
public static int[] factorial(int[] a) {
int[] count = one();
int[] product = one();
while (lessThan(count,a) || equal(count,a)) {
    product = times(product,count);
    count = plus(count,one());
}
return product;
}

// INCOMPLETE
// 
// power
//
// Computes the p-th power of a digit array x, 
// where p is also given as a digit array.  The
// result is calculated as a digit array.
//
public static int[] power(int[] x, int[] p) {
    int pl = length(p);
    int[] checker = new int[1];
    checker[0] = 0;
    int[] adder = new int[1];
    adder[0] = 0;
    if ((p[pl - 1] % 2) == 0)
        {
            while(equal(checker,p) == false)
            {
                adder = plus(square(x),adder);
                p = minus(p,construct("" + 2));
            }
            return adder;
        }
    else
    {
        int[] checkertwo = new int[1];
        checkertwo[0] = 1;
        while(equal(checkertwo,p) == false)
        {
            adder = plus(square(x), adder);
            p = minus(p,construct("" + 2));
        }
        return times(adder,x);
    }
}

public static int[] square(int[] x)
{
    return times(x,x);
}

//
// equal
//
// Returns whether or not two digit arrays 
// represent the same number.
//
public static boolean equal(int[] a, int[] b) {
int[] ta = trim(a);
int[] tb = trim(b);
if (ta.length != tb.length) {
    return false;
} else {
    for (int i = a.length-1; i >= 0; i = i-1) {
    if (a[i] != b[i]) {
        return false;
    }
    }
    return true;
}
}

// INCOMPLETE
//
// lessThan
//
// Returns whether or not one digit array
// represents a number less than another.
//
public static boolean lessThan(int[] a, int[] b) {
boolean value = false;
a = minus(a,construct(""+0));
b = minus(b,construct(""+0));
if(length(b) > length(a))
{
    value = true;
}
else if(length(a) == length(b))
{
    boolean c = false;
    int counter = 0;
    while(counter < length(a))
        {
        c = false;
            if(a[counter] > b[counter])
            {
                c = true;
                value = false;
            }
            if(!c)
                value = true;
            counter++;
        }
}
else
    value = false;
return value;

}

// * * * * * * * * * * * * * * * * * * * * * * * * 
//
// These are helper functions that can be used in 
// the above code.
//

//
// construct
//
// Converts a string that consists of decimal digits
// into an array of those digits.
//
public static int[] construct(String digits) {
int len;
int[] a;

len = digits.length();
a = new int[len];

// Copy each digit of the string into
// the digit array, but as integers 
// rather than characters.

for (int i = len-1; i >= 0; i = i-1) {

    // get the i-th digit
    char c = digits.charAt(i);

    // check if it is a valid digit
    if (c >= '0' && c <= '9') {
    a[len-1-i] = (int)(c-'0');
    } else {
    // treat nondigits as 0 digits
    a[len-1-i] = 0;
    }
}

// trim off leading 0s
return trim(a);
}

//
// zero
//
// returns the digits representing 0
//
public static int[] zero() {
return construct("0");
}

//
// one
//
// returns the digits representing 0
//
public static int[] one() {
return construct("1");
}

//
// trim
//
// Takes an array of integer digits representing an integer,
// one that may have leading 0 digits, and constructs an 
// array with no leading digits.
//
public static int[] trim(int[] a) {
int len = length(a);

int[] b;
// build an array of that length
b = new int[len];

// set the digits
for (int i=0; i<len; i++) {
    b[i] = a[i];
}

return b;
}

// 
// put
//
// Outputs an array of digits, from most- to least-
// significant, excluding any leading 0s.
//
public static void put(int[] a) {
int len = length(a);

for (int i = len-1; i >= 0; i = i-1) {
    TextIO.put(a[i]);
}
}

// 
// putln
//
// Outputs an array of digits, from most- to least-
// significant, excluding any leading 0s, followed by
// a carriage return.
//
public static void putln(int[] a) {
put(a);
TextIO.putln();
}

// 
// length
//
// Counts the number of digits in a digit array
// excluding leading 0s.
//
public static int length(int[] a) {
int len = a.length;

// figure out the number's real length
while (len > 0 && a[len-1] == 0) {
    len = len - 1;
}
if (len == 0) {
    return 1;
} else {
    return len;
}
}

}

我的减号似乎不起作用,出于某种原因,我不知道出了什么问题。我觉得x-y = x +( - y)是我认为我正确做的事情。也许我的教授所写的加功能对此不起作用?我试过想一想。而且我认为这个减函数对于我的除法和幂函数是不可或缺的。对不起,我的笔记不清楚,但是有人可以看一遍,并告诉我最重要的是我在哪里搞砸负功能,因为我认为一旦我得到正确的工作,我就能做到其余部分。

2 个答案:

答案 0 :(得分:0)

此代码未经过测试,但应该可以使用:

public static int[] minus(int[] a, int[] b) {
    int len = length(a);
    int blen = length(b);

    int[] c = new int[len];

    int carry = 0;
    for (int i = 0; i < len; i = i+1) {

        int sum = a[i] - carry;
        if (i < blen) sum -= b[i];
        if (sum < 0) {
            sum += 10;
            carry = 1;
        } else {
            carry = 0;
        }
        c[i] = sum;
    }
}

答案 1 :(得分:0)

plus方法的末尾添加以下代码(在 for 循环中)。

carry = sum / 10; // existing

if (c[i] < 0) {
   c[i] = c[i] + 10; // Create a positive complement of base 10.
   carry = carry - 1; // Borrowed. (or carry = -1)
}

如果没有此修复,当第二个操作数位数较大时,它将返回一个负值,该值在结果中显示为 - digit 。例如,12 + (-8)将打印为1-6