Java 计算平方根时使用BigInteger的性能改进
我试图计算100以下所有整数的平方根,精度高达10000位。我已经试过用牛顿的方法计算大十进制数了,它占用了很多时间 所以现在我用biginger来求平方根(我认为这个方法涉及的计算量更少,并且不需要维护十进制数字)。即使这样,我的代码也会花费很多时间Java 计算平方根时使用BigInteger的性能改进,java,algorithm,biginteger,bigdecimal,square-root,Java,Algorithm,Biginteger,Bigdecimal,Square Root,我试图计算100以下所有整数的平方根,精度高达10000位。我已经试过用牛顿的方法计算大十进制数了,它占用了很多时间 所以现在我用biginger来求平方根(我认为这个方法涉及的计算量更少,并且不需要维护十进制数字)。即使这样,我的代码也会花费很多时间 public class SquareRootHackerRankJarvis { static BigInteger limit; static BigInteger a; static BigInteger b; private stati
public class SquareRootHackerRankJarvis {
static BigInteger limit;
static BigInteger a;
static BigInteger b;
private static BigInteger squareroot(int n, int digits, BigInteger ten,
BigInteger hundred, BigInteger five) {
limit = ten.pow(digits + 1);
a = BigInteger.valueOf(n * 5);
b = BigInteger.valueOf(5);
while (b.compareTo(limit) == -1) {
if (a.compareTo(b) != -1) {
a = a.subtract(b);
b = b.add(ten);
} else {
a = a.multiply(hundred);
b = (b.divide(ten)).multiply(hundred).add(five);
}
}
return b.divide(hundred);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int P = scanner.nextInt();
int sum = 0;
int p = 1;
BigInteger ten = BigInteger.valueOf(10);
BigInteger hundred = BigInteger.valueOf(100);
BigInteger five = BigInteger.valueOf(5);
for (int i = 1; i <= N; i++) {
if (p * p == i) {
p++;
continue;
}
BigInteger x = squareroot(i, P, ten, hundred, five);
char[] digits = x.toString().toCharArray();
for (int j = 0; j <= P - 1; j++) {
sum += Character.getNumericValue(digits[j]);
}
}
System.out.println(sum);
scanner.close();
}}
公共类SquareRootHackerRankJarvis{
静态大整数极限;
静态大整数a;
静态大整数b;
私有静态BigInteger平方根(整数n,整数位数,BigInteger十,
大整数一百,大整数五){
限值=10.pow(位数+1);
a=BigInteger.valueOf(n*5);
b=大整数。值为(5);
而(b.compareTo(limit)=-1){
如果(a.与(b)!=-1相比){
a=a.减去(b);
b=b.加(十);
}否则{
a=a.乘(百);
b=(b.除(十))。乘(百)。加(五);
}
}
返回b.除以(百);
}
公共静态void main(字符串[]args){
扫描仪=新的扫描仪(System.in);
int N=scanner.nextInt();
int P=scanner.nextInt();
整数和=0;
int p=1;
BigInteger十=BigInteger.valueOf(10);
BigInteger百=BigInteger.valueOf(100);
BigInteger五=BigInteger.valueOf(5);
对于(int i=1;i
应移到函数平方根
之外,这样就不会在每次调用函数时创建和初始化它们。请确保它们在此函数中仍然可以访问
BigInteger num;
BigInteger limit;
BigInteger a;
BigInteger b;
应该在函数外部创建,并且应该仅在每次函数调用时初始化
也跟着行
b = (b.divide(ten)).multiply(hundred).add(five);
可以优化为
b = b.multiply(ten).add(five);
除了快速计算非平方根的无数位数之外,还有一个观察结果是,从2到100,只有25个非复合数
接下来,除了像建议的那样引入常数外,将“在后面的5
之前引入0
”减少为两个操作:
static final BigInteger
ten = BigInteger.TEN,
oneHundred = BigInteger.valueOf(100),
five = BigInteger.valueOf( 5),
fourtyFive = BigInteger.valueOf( 45);
/** Computes <code>digits</code> decimal digits of <code>n</code>
* <em>ignoring</em> (decimal) scaling. */
private static BigInteger sqrtDigitsJarvis(int n, int digits) {
BigInteger
limit = ten.pow(digits + 1), // might be an instance data member
a = BigInteger.valueOf(n*5L), // la*100),
b = five; // BigInteger.valueOf(ib*10 - 45);
// flawed for limit < sqrt(5n)
while (b.compareTo(limit) < 0) {
if (0 <= a.compareTo(b)) { // each branch can be parallelised
a = a.subtract(b);
b = b.add(ten);
} else {
a = a.multiply(oneHundred);
b = b.multiply(ten).subtract(fourtyFive);
}
}
return b.divide(oneHundred);
}
Jarvis方法(似乎还有您的代码)计算整数的平方根,而不是像你所说的无理数的平方根。显示的代码非常类似。拉出num
、limit
、a
和b
,然后在调用时重新初始化它们不会使代码线程安全他可以使用私有静态同步BigInteger square根(整数n,整数位数)
在下面的步骤中处理这个问题b=(b.除(十))。乘(百)。加(五);
,我试图在最后一位数字前插入一个零。我认为你给出的方法无法实现这一点。我已经包含了我的全部代码。请查看编辑后的问题。当输入为100(N)和100000(P)时,仍然需要很多时间。还有其他建议吗?
static final BigInteger
ten = BigInteger.TEN,
oneHundred = BigInteger.valueOf(100),
five = BigInteger.valueOf( 5),
fourtyFive = BigInteger.valueOf( 45);
/** Computes <code>digits</code> decimal digits of <code>n</code>
* <em>ignoring</em> (decimal) scaling. */
private static BigInteger sqrtDigitsJarvis(int n, int digits) {
BigInteger
limit = ten.pow(digits + 1), // might be an instance data member
a = BigInteger.valueOf(n*5L), // la*100),
b = five; // BigInteger.valueOf(ib*10 - 45);
// flawed for limit < sqrt(5n)
while (b.compareTo(limit) < 0) {
if (0 <= a.compareTo(b)) { // each branch can be parallelised
a = a.subtract(b);
b = b.add(ten);
} else {
a = a.multiply(oneHundred);
b = b.multiply(ten).subtract(fourtyFive);
}
}
return b.divide(oneHundred);
}