java Java中是否有常用的有理数库?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5442640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:09:02  来源:igfitidea点击:

Is there a commonly used rational numbers library in Java?

javamath

提问by snakile

I'm looking for a Java library which represents fractions (rational numbers). For example, if I want to store the fraction 1/3then it will not be saved as 0.33333which will lose its accuracy.

我正在寻找一个表示分数(有理数)的 Java 库。例如,如果我想存储分数,1/3那么它不会被保存,因为0.33333这将失去其准确性。

Here is some of the functionality I expect finding in such a library:

这是我希望在这样的库中找到的一些功能:

  • getNumerator()
  • getDenominator()
  • add(Rational r1, Rational r2), subtract(Rational r1, Rational r2), multiply(Rational r1, Rational r2), divide(Rational r1, Rational r2)
  • isProper()
  • getCommonDenominator(Collection<Rational> rationals)
  • getSimplified()
  • getNumerator()
  • getDenominator()
  • add(Rational r1, Rational r2), subtract(Rational r1, Rational r2), multiply(Rational r1, Rational r2),divide(Rational r1, Rational r2)
  • isProper()
  • getCommonDenominator(Collection<Rational> rationals)
  • getSimplified()

I can implement such a library by myself, though I was wondering whether something similar already exists.

我可以自己实现这样的库,尽管我想知道是否已经存在类似的东西。

EDIT:It would also be nice if the library implements (in addition to the above) some number theory algorithms, such as getEgyptianFractionsSum()etc.

编辑:如果库实现(除上述之外)一些数论算法,例如getEgyptianFractionsSum()等,那也会很好。

采纳答案by trashgod

The JSciencelibrary includes the class org.jscience.mathematics.number.Rational. In additional to the usual factories, accessors and operations, one can construct other useful entities, including Polynomial<Rational>, Vector<Rational>and Matrix<Rational>.

JScience库包括的类org.jscience.mathematics.number.Rational。除了通常的工厂、访问器和操作之外,还可以构造其他有用的实体,包括Polynomial<Rational>Vector<Rational>Matrix<Rational>

As an example, a function to obtain the lowest common denominator of a collection of fractions might look like this:

例如,获取分数集合的最小公分母的函数可能如下所示:

private static LargeInteger lcd(Collection<Rational> fractions) {
    Rational sum = Rational.ZERO;
    for (Rational rational : fractions) {
        sum = sum.plus(rational);
    }
    return sum.getDivisor();
}

The following statement prints 6:

以下语句打印6

System.out.println(lcd(Arrays.asList(
    Rational.valueOf(1, 2), Rational.valueOf(1, 3))));

回答by Petar Minchev

Does Apache Commons Mathsuit you?

阿帕奇共享数学适合你?

回答by hardmath

I'm not sure how commonly used it is, but the apfloat packages (Java and C++) contain a class for rational arithmetic.

我不确定它有多常用,但 apfloat 包(Java 和 C++)包含一个用于有理算术的类

回答by mP.

The Apfloat library has lots of great features, performance, accuracy and so on. Its definitely a better BigDecimal which to be fair works but is quite simple and offers little functionality.

Apfloat 库具有许多出色的功能、性能、准确性等。它绝对是一个更好的 BigDecimal,它是公平的,但非常简单并且提供的功能很少。

http://www.apfloat.org/apfloat_java/

http://www.apfloat.org/apfloat_java/

Contents:

内容:

Classpath setting First example Constructing Apfloats Double and float constructor caveats Apfloats are immutable Precision Output Advanced mathematical functions Integers Complex numbers Rational numbers Using some other radix than 10 Equality and comparison Formatting

类路径设置 第一个示例 构造 Apfloats Double 和 float 构造函数警告 Apfloats 是不可变的 精度输出 高级数学函数 整数 复数 有理数 使用除 10 以外的其他基数 相等和比较 格式

回答by Suat KARAKUSOGLU

I implemented a small class that can be used for that purposes, maybe it can be useful for you as well, use with caution.

我实现了一个可以用于该目的的小类,也许它对您也有用,请谨慎使用。

import java.util.ArrayList;

public class RationalNumber {

    /**
     *
     * @author Suat KARAKUSOGLU
     * @email  [email protected]
     * This class has 2 kind of constructors
     * 1. is RationalNumber a=new RationalNumber("3.3");
     *       RationalNumber a=new RationalNumber("-3.3");
     * With this constructor one can enter the decimal number and also specify whether negative or not
     *
     * 2. is RationalNumber a=new RationalNumber(3,5);
     * With this constructor the first value is nominator and second one is denominator.
     *
     * The advantage side of this class is, it prevents the fractional errors while dividing
     * RationalNumber keeps all denominator and nominator values as it is and when the real value is
     * needed, the calculation occurs at that time.
     *
     * Supports multiply,divide,add,subtract operations on RationalNumber classes.
     *
     */


    /*
     * Simple Usage:
     *
     * RationalNumber a=new RationalNumber("3.3");
     * RationalNumber b=new RationalNumber("4.5");
     * System.out.println("a ="+a.getStringValue());
     * System.out.println("b ="+b.getStringValue());
     * System.out.println("a-b ="+a.subtract(b).getStringValue());
     * System.out.println("a ="+a.getStringValue());
     * System.out.println("b ="+b.getStringValue());
     * RationalNumber k=a.divide(b);
     * System.out.println("a/b="+k.getStringValue());
     * System.out.println("a/b="+k.getDoubleValue());
     *
     * System out results:
     *
     * a =33/10
     * b =9/2
     * a-b =-6/5
     * a =33/10
     * b =9/2
     * a/b=11/15
     * a/b=0.7333333333333333
     *
     */

    public ArrayList<Long> nominators = new ArrayList<Long>();
    public ArrayList<Long> denominators = new ArrayList<Long>();

    public RationalNumber(String rationalNumberStringValue) {
        this(parseRationalNumberStringValue(rationalNumberStringValue)[0],
                parseRationalNumberStringValue(rationalNumberStringValue)[1]);

    }

    private static Long[] parseRationalNumberStringValue(
            String rationalNumberStringValue) {

        boolean positive = true;
        if (rationalNumberStringValue.charAt(0) == '-') {
            positive = false;
            rationalNumberStringValue = rationalNumberStringValue.substring(1);
        }

        // 0. index is keeping nominator
        // 1. index is keeping denominator
        Long[] nominatorDenominator = new Long[2];
        nominatorDenominator[0] = 1l;
        nominatorDenominator[1] = 1l;

        String[] splittedNumberArr = rationalNumberStringValue.split("\.");
        String denominatorStr = splittedNumberArr[1];

        for (int i = 0; i < denominatorStr.length(); i++) {
            nominatorDenominator[1] *= 10;
        }

        rationalNumberStringValue = removeCharAt(rationalNumberStringValue,
                rationalNumberStringValue.indexOf('.'));
        nominatorDenominator[0] = Long.valueOf(rationalNumberStringValue);
        if (!positive) {
            nominatorDenominator[0] *= -1;
        }
        return nominatorDenominator;

    }

    public static String removeCharAt(String s, int pos) {
        return s.substring(0, pos) + s.substring(pos + 1);
    }

    public RationalNumber(Integer nominator, Integer denominator) {

        this((long) nominator, (long) denominator);

    }

    public RationalNumber(Long nominator, Long denominator) {

        nominators.add(nominator);
        denominators.add(denominator);
        simplify();

    }

    public RationalNumber(ArrayList<Long> nominatorList,
            ArrayList<Long> denominatorList) {

        nominators.addAll(nominatorList);
        denominators.addAll(denominatorList);
        simplify();

    }

    public String getStringValue() {
        return getMultipliedValue(this.nominators) + "/"
                + getMultipliedValue(this.denominators);
    }

    public double getDoubleValue() {
        return (double) getMultipliedValue(this.nominators)
                / (double) getMultipliedValue(this.denominators);
    }

    public RationalNumber multiply(RationalNumber rationalNumberToMultiply) {

        RationalNumber mulResult = new RationalNumber(
                rationalNumberToMultiply.nominators,
                rationalNumberToMultiply.denominators);
        mulResult.nominators.addAll(this.nominators);
        mulResult.denominators.addAll(this.denominators);

        return RationalNumber.simplifyRationalNumber(mulResult);
    }

    public RationalNumber divide(RationalNumber rationalNumberToDivide) {

        RationalNumber divideResult = new RationalNumber(
                rationalNumberToDivide.nominators,
                rationalNumberToDivide.denominators);

        // division means multiplication with reverse values
        ArrayList<Long> tempLongList = divideResult.nominators;
        divideResult.nominators = divideResult.denominators;
        divideResult.denominators = tempLongList;

        return this.multiply(divideResult);

    }

    public RationalNumber add(RationalNumber rationalNumberToAdd) {

        rationalNumberToAdd = RationalNumber
                .simplifyRationalNumber(rationalNumberToAdd);

        return new RationalNumber(
                (getMultipliedValue(this.nominators) * getMultipliedValue(rationalNumberToAdd.denominators))
                        + (getMultipliedValue(this.denominators) * getMultipliedValue(rationalNumberToAdd.nominators)),
                (getMultipliedValue(this.denominators) * getMultipliedValue(rationalNumberToAdd.denominators)));

    }

    public RationalNumber subtract(RationalNumber rationalNumberToSubtract) {

        rationalNumberToSubtract = RationalNumber
                .simplifyRationalNumber(rationalNumberToSubtract);

        RationalNumber subtractTempRational = new RationalNumber(
                rationalNumberToSubtract.nominators,
                rationalNumberToSubtract.denominators);

        // Multiply one of its nominators negative value
        subtractTempRational.nominators.set(0,
                (subtractTempRational.nominators.get(0) * -1));

        // add with its negative value
        return this.add(subtractTempRational);

    }

    private long getMultipliedValue(ArrayList<Long> longList) {
        Long mulResult = 1l;
        for (Long tempLong : longList) {
            mulResult *= tempLong;
        }
        return mulResult;
    }

    // simplifies original rationalnumber
    public void simplify() {
        long tempGcd = 1;
        long iValue = 1;
        long jValue = 1;
        for (int i = 0; i < this.nominators.size(); i++) {
            iValue = this.nominators.get(i);
            for (int j = 0; j < this.denominators.size(); j++) {
                jValue = this.denominators.get(j);
                tempGcd = gcd(iValue, jValue);
                this.nominators.set(i, iValue / tempGcd);
                this.denominators.set(j, jValue / tempGcd);
            }
        }
    }

    public static RationalNumber simplifyRationalNumber(
            RationalNumber rationalNumberToSimplify) {
        long tempGcd = 1;
        long iValue = 1;
        long jValue = 1;
        for (int i = 0; i < rationalNumberToSimplify.nominators.size(); i++) {
            for (int j = 0; j < rationalNumberToSimplify.denominators.size(); j++) {
                iValue = rationalNumberToSimplify.nominators.get(i);
                jValue = rationalNumberToSimplify.denominators.get(j);
                tempGcd = gcd(iValue, jValue);
                rationalNumberToSimplify.nominators.set(i, iValue / tempGcd);
                rationalNumberToSimplify.denominators.set(j, jValue / tempGcd);
            }
        }
        return rationalNumberToSimplify;
    }

    // Euclidean algorithm to find greatest common divisor
    public static long gcd(long a, long b) {

        a = Math.abs(a);
        b = Math.abs(b);

        if (a < b) {
            long temp = a;
            a = b;
            b = temp;
        }

        if (b == 0)
            return a;
        else
            return gcd(b, a % b);
    }

    public RationalNumber add(int integerToAdd) {

        RationalNumber tempRationalNumber=new RationalNumber(integerToAdd,1);
        return this.add(tempRationalNumber);
    }
    public RationalNumber subtract(int integerToSubtract) {

        RationalNumber tempRationalNumber=new RationalNumber(integerToSubtract,1);
        return this.subtract(tempRationalNumber);
    }
    public RationalNumber multiply(int integerToMultiply) {

        RationalNumber tempRationalNumber=new RationalNumber(integerToMultiply,1);
        return this.multiply(tempRationalNumber);
    }
    public RationalNumber divide(int integerToDivide) {

        RationalNumber tempRationalNumber=new RationalNumber(integerToDivide,1);
        return this.divide(tempRationalNumber);
    }



}