再谈Java精度计算问题
前文使用Java高精度计算 2 \sqrt2 2,采用二分法,精度达到小数点后2500位,其实是不准确的。因为控制台上并没有显示数据(一行超过一定数量的字符时系统默认无法显示),但并不代表没有数据。测试了一下,大概小数点后超过2728位后,无法正常显示;超过3700位后,计算时间比较长,这也是二分法的缺陷。在网上搜索了一阵子,有一个程序说是能够计算到小数点后上万位。但把代码复制过来后发现这个程序只是片段(函数),需要自己找出实参。试了一下,还是很快找到了。这一次把获得的数据先转换成字符串,然后写到一个文件里。壮着胆子把精度写成1000000(一百万),程序运行后等了大概20秒左右,结束了,看一下那个data.txt文件,乖乖,977k,用Notepad无法打开,使用写字板打开,数据真的有,与Python写的10000比较一下,后来发现Python的少一位,才知道,Python指定的那个prec是指数据的所有位,在探索的路上,谁也不能保证所获得的认知都是正确的,有可能是片面的,甚至有可能是错误的。
package sqrt;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.io.Writer;
import java.io.FileWriter;
public class sqrt1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
File file= new File("data.txt");
if (!file.exists()) {
try {
file.createNewFile(); //如果文件不存在则创建文件
} catch (IOException e) {
e.printStackTrace();
}
}
BigDecimal A = new BigDecimal("2");
final int SCALE = 1000000; //精度设置为小数点后一百万位
BigDecimal x0 = new BigDecimal("0");
BigDecimal x1 = new BigDecimal(Math.sqrt(A.doubleValue()));
BigDecimal x2 = new BigDecimal("2");
while (!x0.equals(x1)) {
x0 = x1;
x1 = A.divide(x0, SCALE, BigDecimal.ROUND_HALF_UP); //这两行可以理解为反复求精
x1 = x1.add(x0).divide(x2, SCALE, BigDecimal.ROUND_HALF_UP);
}
System.out.println(x1);
String str = String.valueOf(x1); //把BigDecimal类型数据转换成字符串
writeInFile(file,str);
}
private static void writeInFile(File file, String content) {
Writer writer = null;
StringBuilder outputString = new StringBuilder();
try {
outputString.append(content + "\r\n");
writer = new FileWriter(file, true); // true表示追加
writer.write(outputString.toString());
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
writer.close();
}
catch (IOException e2) {
e2.printStackTrace();
}
}
}
}