如何在 Java 中实现无穷大?

Posted

技术标签:

【中文标题】如何在 Java 中实现无穷大?【英文标题】:How to implement infinity in Java? 【发布时间】:2012-10-08 18:08:50 【问题描述】:

对于每种数值数据类型,Java 有什么东西可以表示无穷大吗?它是如何实现的,以便我可以用它进行数学运算?

例如

int myInf = infinity; //However it is done
myInf + 5; //returns infinity
myInf*(-1); //returns negative infinity

我尝试过使用非常大的数字,但我想要一个合适的简单解决方案。

【问题讨论】:

无穷无尽,你想建模哪一个? 为什么∞-∞==0 应该是真的?还有:你为什么需要这样的东西? 【参考方案1】:

double 支持无限

double inf = Double.POSITIVE_INFINITY;
System.out.println(inf + 5);
System.out.println(inf - inf); // same as Double.NaN
System.out.println(inf * -1); // same as Double.NEGATIVE_INFINITY

打印

Infinity
NaN
-Infinity

注意:Infinity - Infinity 不是数字

【讨论】:

我尽可能避免使用float,因为它的精度很差。 ;) 实现像 Dijkstra 这样的算法让我怀疑 POSITIVE_INFINITY 【参考方案2】:

我假设您使用整数数学是有原因的。如果是这样,您可以通过使用 Integer 类的 MAX_VALUE 字段获得与 POSITIVE_INFINITY 功能几乎相同的结果:

Integer myInf = Integer.MAX_VALUE;

(对于 NEGATIVE_INFINITY,您可以使用 MIN_VALUE。)当然会有一些功能差异,例如,将 myInf 与恰好是 MAX_VALUE 的值进行比较时:显然这个数字不小于 myInf。此外,如下面的 cmets 所述,增加正无穷大将使您返回负数(而减少负无穷大将使您返回正数)。

还有 a library 实际上有字段 POSITIVE_INFINITY 和 NEGATIVE_INFINITY,但它们实际上只是 MAX_VALUE 和 MIN_VALUE 的新名称。

【讨论】:

Integer.MAX_VALUE + 5 是多少? Integer.MAX_VALUE + 5 环绕成负整数。整数.MAX_VALUE + 5 = 整数.MIN_VALUE + 4 = -2147483644。 使用Integer.MAX_VALUEDouble.POSITIVE_INFINITY 有什么区别,你说它们“功能几乎相同”,那么有什么区别? @ahitt6345 Integer.MAX_VALUE 仍然是有限的,它只是模仿无限的一种技巧。此外,Integer.MAX_VALUE 只有 32 位,而Double.POSITIVE_INFINITY 是 64 位。 Integer.MAX_VALUE 是可以在您的输入中使用的有效数字。 op 要求无穷大,它不是一个数字,而是一个数学符号。【参考方案3】:

要使用Infinity,可以使用支持InfinityDouble:-

    System.out.println(Double.POSITIVE_INFINITY);
    System.out.println(Double.POSITIVE_INFINITY * -1);
    System.out.println(Double.NEGATIVE_INFINITY);

    System.out.println(Double.POSITIVE_INFINITY - Double.NEGATIVE_INFINITY);
    System.out.println(Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY);

输出:-

Infinity
-Infinity
-Infinity

Infinity 
NaN

【讨论】:

【参考方案4】:

DoubleFloat 类型具有 POSITIVE_INFINITY 常量。

【讨论】:

@user1753100:默认情况下没有,但是一些库,比如这个:jscience.org 显然实现了它。 将无限值限制为 Doubles 和 Floats 似乎是任意的。它们的最大值比 Integers 的最大值更接近无穷大,但不会更接近。 @PatrickBrinich-Langlois 浮点类型(例如 double 和 float)通常能够直接表示无穷大(即,有一个位模式专门表示“无穷大”,与最大值不同类型)。 Double 和 Float 具有 MAX_VALUE,与 Integer 相同。 "它们的最大值比 Integers 的最大值更接近于无穷大,但不会更接近。"。任何有限数都离无限远;)【参考方案5】:

我不确定 Java 是否对每种数值类型都有无穷大,但对于某些数值数据类型,答案是肯定的:

Float.POSITIVE_INFINITY
Float.NEGATIVE_INFINITY

Double.POSITIVE_INFINITY
Double.NEGATIVE_INFINITY

您还可能会发现以下文章很有用,它代表了一些涉及 +/- 无穷大的数学运算:Java Floating-Point Number Intricacies。

【讨论】:

【参考方案6】:

只有 Double 和 Float 类型支持 POSITIVE_INFINITY 常量。

【讨论】:

【参考方案7】:

对于数字包装类型。

例如 Double.POSITVE_INFINITY

希望这对你有帮助。

【讨论】:

不适用于所有数字包装器类型。仅适用于 Double 和 Float。【参考方案8】:

一个通用的解决方案是引入一个新类型。它可能涉及更多,但它具有适用于任何未定义自己的无穷大的类型的优势。

如果T 是定义了lteq 的类型,则可以使用lteq 定义InfiniteOr<T>,如下所示:

class InfiniteOr with type parameter T:
    field the_T of type null-or-an-actual-T
    isInfinite()
        return this.the_T == null
    getFinite():
        assert(!isInfinite());
        return this.the_T
    lteq(that)
        if that.isInfinite()
            return true
        if this.isInfinite()
            return false
        return this.getFinite().lteq(that.getFinite())

我会留给你把它翻译成准确的 Java 语法。我希望这些想法很清楚;不过还是让我把它们拼出来吧。

我们的想法是创建一个新类型,它的值与某个已经存在的类型具有所有相同的值,加上一个特殊值——就你可以通过公共方法来说——完全按照你希望无穷大的行为方式行事,例如它比其他任何东西都重要。我在这里使用null 来表示无穷大,因为这在Java 中似乎是最直接的。

如果你想添加算术运算,决定它们应该做什么,然后实现它。如果您首先处理无限情况,然后在原始类型的有限值上重用现有操作,这可能是最简单的。

在处理左侧无穷大之前处理右侧无穷大或反之亦然的惯例是否有益,可能存在也可能不存在一般模式;如果不尝试,我无法判断,但对于小于或等于 (lteq),我认为首先查看右侧无穷大更简单。我注意到lteq不是可交换的,但addmul 是;也许这是相关的。

注意:想出一个关于无限值应该发生什么的良好定义并不总是那么容易。它用于比较,加法和乘法,但可能不是减法。此外,您可能需要注意无限基数和序数之间的区别。

【讨论】:

使用额外的枚举字段来表示额外的状态可能是值得的,因此您也可以使用 负无穷大,这通常是可取的,并且使@987654331 @ 好好工作。这也将允许您支持 NaN(不是数字)概念。除此之外,在整数类型之上添加特殊值可能是一个好主意,特别是当应用程序需要浮点数违反的语义时。【参考方案9】:

整数无穷大:

  Integer maxNumber = Integer.MAX_VALUE

双无穷

  Double maxNumber = Double.MAX_VALUE;
  Double positiveInf = Double.POSITIVE_INFINITY;
  Double negativeInf = Double.NEGATIVE_INFINITY

浮点数

   Float positiveInf = Float.POSITIVE_INFINITY;
   Float negativeInf = Float.NEGATIVE_INFINITY
   Float maxNumber = Float.MAX_VALUE;

【讨论】:

我认为 Integer.MAX_VALUE 是一个可实现的值,因此可以通过可表示的位数进行匹配。这并不总是很重要,因为不可能有更大的数字,因为 +1 会溢出到 Integer.MIN_VALUE。无论如何,它与 Infinity 不太一样? 但是,您可以在许多情况下使用 MAX_VALUE,例如合并排序,如果它可以用作“哨兵值”。例如,如果您想返回一对中最小的一个,并且碰巧将哨兵与列表中出现的值 2147483647 进行了比较。你返回哪个并不重要。 唯一的问题是,如果您的输入中有正确的 MAX_VALUE 组合,您可能会迭代超出数组的索引。此时你不妨放下哨兵,只检查列表的长度。【参考方案10】:

由于类 Number 不是最终的,这里有一个 想法,我在其他帖子中还没有找到。 即对类号进行子类化。

这会以某种方式传递一个可以处理的对象 作为 Integer、Long、Double、Float 的无穷大, BigInteger 和 BigDecimal。

由于只有两个值,我们可以使用单例模式:

public final class Infinity extends Number 
    public final static Infinity POSITIVE = new Infinity(false);
    public final static Infinity NEGATIVE = new Infinity(true);
    private boolean negative;
    private Infinity(boolean n) 
        negative = n;
    

不知何故我认为剩下的方法 intValue(), longValue() 等等......然后应该被覆盖以引发异常。以便 如果没有进一步的预防措施,则无法使用无穷大值。

【讨论】:

【参考方案11】:

我是 Java 初学者... 我在 Java 文档中为 booleandouble 类型找到了另一个无穷大的实现。 https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3

正零和负零比较相等;因此结果 表达式 0.0==-0.0 为真,0.0>-0.0 的结果为假。但 其他操作可以区分正负零;为了 例如,1.0/0.0 的值为正无穷大,而值为 1.0/-0.0 是负无穷大。

它看起来很难看,但它确实有效。

public class Main 

    public static void main(String[] args) 
        System.out.println(1.0/0.0);
        System.out.println(-1.0/0.0);
    


【讨论】:

以上是关于如何在 Java 中实现无穷大?的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中实现接口类

如何在 Java 中实现 Chebyshev Type 2 LPF?

如何在 Java 中实现过滤迭代器?

如何在 Java 类中实现运算符

如何在 Java 中实现包装装饰器?

Java 7:如何在 Java 中实现拖放?