Java中利用BigInteger類進行大數開方


  在Java中有時會用到大數據,基本數據類型的存儲范圍已經不能滿足要求了,如要對10的1000次方的這樣一個數據規模的數進行開方運算,很明顯不能直接用Math.sqrt()來進行計算,因為已經溢出了。 

  牛頓迭代法(Newton's method)又稱為牛頓-拉夫遜方法(Newton-Raphson method),它是牛頓在17世紀提出的一種在實數域和復數域上近似求解方程的方法。多數方程不存在求根公式,因此求精確根非常困難,甚至不可能,從而尋找方程的近似根就顯得特別重要。方法使用函數f(x)的泰勒級數的前面幾項來尋找方程f(x) = 0的根。牛頓迭代法是求方程根的重要方法之一,其最大優點是在方程f(x) = 0的單根附近具有平方收斂,而且該法還可以用來求方程的重根、復根。另外該方法廣泛用於計算機編程中。

設r是f(x) = 0的根,選取x0作為r初始近似值,過點(x0,f(x0))做曲線y = f(x)的切線L,L的方程為y = f(x0)+f'(x0)(x-x0),求出L與x軸交點的橫坐標 x1 = x0-f(x0)/f'(x0),稱x1為r的一次近似值。

  下面以藍橋杯的一個題為例:

問題描述
  小明先把硬幣擺成了一個 n 行 m 列的矩陣。

  隨后,小明對每一個硬幣分別進行一次 Q 操作。

  對第x行第y列的硬幣進行 Q 操作的定義:將所有第 i*x 行,第 j*y 列的硬幣進行翻轉。

  其中i和j為任意使操作可行的正整數,行號和列號都是從1開始。

  當小明對所有硬幣都進行了一次 Q 操作后,他發現了一個奇跡——所有硬幣均為正面朝上。

  小明想知道最開始有多少枚硬幣是反面朝上的。於是,他向他的好朋友小M尋求幫助。

  聰明的小M告訴小明,只需要對所有硬幣再進行一次Q操作,即可恢復到最開始的狀態。
然而小明很懶,不願意照做。於是小明希望你給出他更好的方法。幫他計算出答案。
輸入格式
  輸入數據包含一行,兩個正整數 n m,含義見題目描述。
輸出格式
  輸出一個正整數,表示最開始有多少枚硬幣是反面朝上的。
樣例輸入
2 3
樣例輸出
1
數據規模和約定
  對於10%的數據,n、m <= 10^3;
  對於20%的數據,n、m <= 10^7;
  對於40%的數據,n、m <= 10^15;
  對於10%的數據,n、m <= 10^1000(10的1000次方)。
  利用牛頓迭代法可以求解,代碼如下:
 

 

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;

public class fz {

public static void main(String[] args) {


Scanner cin =new Scanner(System.in);

//for(int i=1;i<100;i++){
// BigInteger n=cin.nextBigInteger();
// System.out.println("......"+myBigNumSqrt(n));}


BigInteger n=cin.nextBigInteger();
BigInteger m=cin.nextBigInteger();
BigInteger tem=myBigNumSqrt(n).multiply(myBigNumSqrt(m));
System.out.println(tem);

}

//大數開方
public static BigInteger myBigNumSqrt(BigInteger xx)
{
BigDecimal x=new BigDecimal(xx);
BigDecimal n1=BigDecimal.ONE;
BigDecimal ans=BigDecimal.ZERO;
//int i=1;
while((n1.multiply(n1).subtract(x)).abs().compareTo(BigDecimal.valueOf(0.001))==1)
{
//System.out.println(i+"..."+n1);
//i++;
BigDecimal s1=x.divide(n1,2000,BigDecimal.ROUND_HALF_UP);
BigDecimal s2=n1.add(s1);
n1=s2.divide(BigDecimal.valueOf(2),2000,BigDecimal.ROUND_HALF_UP);

}
ans=n1;
//System.out.println(ans);
BigInteger rt =new BigInteger(ans.toString().split("\\.")[0]);
return rt;
}
}

輸出實例:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM