我有两个等式:x * x - D * y * y = 1
和x = sqrt(1 + D * y * y)
。
两者都是另一方的代数操纵。
给定D,我需要求解x的最小整数值,以便y也是一个整数。我遍历可能的y值,将它们插入第二个等式并测试x是否为整数。如果是,我会返回x。
我遇到的问题是当x,y和D插入第一个等式时,它不等于1.
这些是一些有问题的价值观:
1. x=335159612 y=42912791 D=61
2. x=372326272 y=35662389 D=109
我的直觉是java的Math.sqrt
方法不会计算这么小的小数,但是BigDecimal
没有平方根方法。
我的数学错了吗?如果没有,我该怎么做才能准确计算x和y?
编辑:这是问题的根源以及测试double是否是自然数的方法。
public static void main(String[] args){
long x = 335159612, D = 61, y = 42912791;
System.out.println(Math.sqrt(D * y * y + 2)); // 3.35159612E8
System.out.println(x * x - D * y * y); // 3
}
public static boolean isNatural(double d){
return d == (int)d;
}
答案 0 :(得分:1)
答案 1 :(得分:1)
请注意双重'
中的精确度根据IEEE 754-1985,双精度提供16位数字(159绝对精确)。
E.g。 a)SQRT(112331965515990542)
335159611.99999999701634694576505237017910
当转换为double时,给出3.3515961199999999E8
b)SQRT(112331965515990543)
335159611.99999999850817347288252618840968
当转换为double时,给出3.3515961199999999E8。 因此,根据IEEE 754-1985定义,这些值是相等的。 显然,任何进一步的逻辑/数学检查一般来说都是不准确的。
为克服此限制,我建议使用www.javasoft.ch
中的BigMath包import ch.javasoft.math.BigMath;
import java.math.BigDecimal;
class Tester {
public static void main(String[] args) {
long D = 61L, y = 42912791L;
double a = Math.sqrt(D * y * y + 1);
double b = Math.sqrt(D * y * y + 2);
System.out.println(a);
System.out.println(b);
System.out.println(a == b);
BigDecimal bda = BigMath.sqrt(new BigDecimal(D * y * y + 1), 32);
BigDecimal bdb = BigMath.sqrt(new BigDecimal(D * y * y + 2), 32);
System.out.println(bda.toString());
System.out.println(bdb.toString());
System.out.println(bda.equals(bdb));
}
}
结果:
3.35159612E8
3.35159612E8
true
335159611.99999999701634694576505237017910
335159611.99999999850817347288252618840968
false
P.S。要完全毁掉你对标准Java数学的信念,试试这个:
System.out.println(0.9200000000000002);
System.out.println(0.9200000000000001);
你会看到:
0.9200000000000002
0.9200000000000002
答案 2 :(得分:0)
如果问题是sqrt,请改用第一个等式。如果x是整数,则x ^ 2也将是整数;如果x不是整数,则x ^ 2也不是整数,只要你使用的BigDecimals具有足够的数学量级而不是双倍。