【问题标题】:Why does "big = big.add(..)" need to be used to sum BigIntegers?为什么需要使用“big = big.add(..)”来对 BigIntegers 求和?
【发布时间】:2015-08-01 06:07:03
【问题描述】:

我是初学者。这可能是一个愚蠢的问题。

我有一个非常大的数字数组。我需要找到数组中所有这些数字的总和。我定义了一个 BigInteger 并将其初始化为零。现在我将遍历数组并将每个元素添加到这个 BigInteger 中。

BigInteger big = BigInteger.ZERO;
for(BigInteger b : array){
   big.add(b);
}

没有编译错误,但big 的值仍然为零,代码不起作用。所以,我检查了它并了解到 BigInteger add 方法返回总和。我修改了上面的代码。

big = big.add(b);

现在这工作正常。

我的问题:那里到底发生了什么?为什么第一个代码没有更新big值。

我可以将这个BigInteger.add()collection.add() 进行比较

感谢您提供更多见解。谢谢。

【问题讨论】:

    标签: java arrays add biginteger


    【解决方案1】:

    为什么第一个代码没有更新大值。

    BigInteger 是不可变的,您无法更改它,就像更改 String 或任何原始包装器一样。

    例如

    String s = "Hello ";
    s.concat("World"); // doesn't change anything.
    
    s = s.concat("World"); // Updates 's'
    

    我可以将这个 BigInteger.add() 与 collection.add() 进行比较

    集合是可变的,但这个标量值不是。

    使用可变对象在很大程度上是一种性能上的让步。如果您有一个每次都需要完整副本的集合,那么它的性能会很差。

    【讨论】:

    • @Charan 如果集合很大,创建一个包含与现有引用几乎完全相同的引用的新集合可能会很昂贵。可变集合允许人们在不做这项工作的情况下获得一个稍微修改过的集合版本。
    • @Charan 将元素添加到一百万个元素的 ArrayList 可以像引用分配和计数器增量一样简单。要复制和添加,您必须复制所有参考文献,全部数百万只是为了添加一个。顺便说一句,CopyOnWriteArrayList 这样做并且修改大型集合非常慢。
    • @PeterLawrey 谢谢,知道了!
    【解决方案2】:

    这是该方法的 JavaDoc

    public BigInteger add(BigInteger val)
    Returns a BigInteger whose value is (this + val).
    
    Parameters:
    val - value to be added to this BigInteger.
    
    Returns:
    this + val
    

    这意味着它不是修改值,而是计算一个新值并返回它。当您执行big = big.add(b) 时,您正在运行该方法,获取结果值,并用它替换 big 的原始值。

    考虑使用整数、x 和 y 的等价物。

    int x = 3;
    int y = 4;
    x + y; // At this point, x is still 3 - as you've not assigned the result of this calculation anywhere
    x = x + y; // Now - x will be 7
    

    【讨论】:

      【解决方案3】:

      我的问题:那里到底发生了什么?为什么没有第一 代码更新大价值。

      因为它是不可变的任意精度整数,这意味着当您调用add 方法时它实际上不会更改原始整数,而是创建一个新整数。注意不可变意味着一旦Object已创建,其状态无法更改。例如String,Integer,Float 等。

      Integer i = new Integer(10);//State 1
      i = new Integer(20);//State 2 but does not update state 1
      

      big.add(b); 相加后返回的值需要存储在其他或同一个变量中。

      看看 add 方法在这里做了什么,

      public BigInteger add(BigInteger val) {
          if (val.signum == 0)
              return this;
          if (signum == 0)
              return val;
          if (val.signum == signum)
              return new BigInteger(add(mag, val.mag), signum);
      
          int cmp = compareMagnitude(val);
          if (cmp == 0)
              return ZERO;
          int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
                             : subtract(val.mag, mag));
          resultMag = trustedStripLeadingZeroInts(resultMag);
          //Here it's creating new Object
          return new BigInteger(resultMag, cmp == signum ? 1 : -1);//<====
      }
      

      我可以将这个 BigInteger.add() 与 collection.add() 进行比较

      这里说List.add实际上会将元素添加到列表中,您可以更改该元素的值并注意List.add不会创建新元素,但它实际上添加了原始元素的引用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-26
        • 2015-07-18
        • 1970-01-01
        • 2018-05-11
        • 2014-10-01
        相关资源
        最近更新 更多