说起编程中的高精度数值,我第一反应就是double类型了。的确,double阶码11位,尾数52位,几乎能应对任何苛刻的要求......然而,当我天真地尝试用double来算泰勒展开式的函数值,离散代数的狰狞性瞬间完全暴露眼前。

我不是数学出身,也并不关心那些奇异的函数形式。我只是想推导一个物理系统的冲击响应函数。那个函数没法求得解析解,我只好用皮卡迭代法求泰勒级数式。经过一番挣扎,级数通项终于确定了,但是函数的绘图却成了隐藏难题。

函数的形式:

\[f(x)={\sum_{n=1}^{\infty}{\frac{(-1)^n*2n}{2^n*(n!)^2}*x^{2n-2}}}
\]

函数形似一个衰减的正弦振荡,本应该长这样:

但是实际上泰勒级数绘制出来长这样:

甚至这样:

崩溃了,仔细检查原因,发现最后几项级数取值超过\(10^{300}\),换言之double活生生撑爆了。。。

接下来的几天我在网上查找了半天提高浮点数长度(精度)的方法,但是收获甚微。python的numpy好似有float_128,但其实是80位扩展double。c语言倒是找到了诸如mpfr之类的4精度数计算包,但是这也是治标不治本。

由于我用java做科学计算的习惯(奇异癖好),我决定用java写一个任意精度浮点数计算工具(类)。

LFloat类(large float)原理:

由于电脑显然不能存储太长的数字,我决定用long数组存储浮点数的小数部分。并且,考虑到乘法的计算问题,如果两个long类型的整数直接相乘,最多会有接近64位(二进制)的得数由于long溢出而丢弃,从而达不到准确计算的目的。最后,我只能妥协,每一个long储存32位(二进制)小数部分。

这样的好处在于对于加减乘法,0-31位的进位部分会保存在31-63位处,从而方便后续处理。对于除法,我没有采用较为高效的方法,而只是朴素的逐位作差实现。

另一个难点是数字的输入与输出。由于精度变态,double输入显然不太合适(除了极个别数,一般的double数都是做了近似截断的,不会太准确)。为此只能输入String字符串,再自定义parse函数来读取、存储数字。对于显示,则采取读取数字的逆运算,经过一系列的2-10转换最终输出。

输入输出还有一个难点,即指数的转化。输入、输出的数字都由科学计数法表示,动辄“1E+1000”之类的天文数字。为了便于转化,所有数字输入时都先取log,求出阶码,再用exp函数算出小数部分的二进制数。

成果:

  • 实现了任意指定精度的浮点数的运算,并且阶码有62位,最大能表示\(10^{10^{18}}\)这等天文数字!
  • 浮点数运算近似符合IEEE 754标准,处理舍入方面直接截断,而没有向偶数取整(其实不太需要,感觉精度差了就多加几位精度呗~)。

一些测试,以及计算\(\pi\)的数值到400位:

代码:

见我的github页面,测试代码也在里面,注释较为详细。

结束语:

经过千辛万苦终于写成了较为高效的高精度浮点数计算代码,编写期间排除bug无数,希望这个工具对大家有所帮助。

p.s.如果有人发现了什么bug(一定有的),或者提出什么可以改进的地方,欢迎留言~

Java 高精度浮点数计算工具的更多相关文章

  1. java第二周的学习知识4(对原码,补码,反码和java中浮点数计算不准确的总结)

    原码:一个正数,转换为二进制位就是这个正数的原码.负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码. 但是原码有几个缺点,零分两种 +0 和 -0 .很奇怪是吧!还有,在进行不同符号的加法运 ...

  2. JAVA简单精确计算工具类

    1 public class ArithUtil { 2 3 // 默认除法运算精度 4 private static final int DEF_DIV_SCALE = 10; 5 6 privat ...

  3. 计算价格, java中浮点数精度丢失的解决方案

    计算价格, java中浮点数精度丢失的解决方案

  4. java精确计算工具类

    java精确计算工具类 import java.math.BigDecimal; import java.math.RoundingMode; import java.math.BigDecimal; ...

  5. 学以致用:手把手教你撸一个工具库并打包发布,顺便解决JS浮点数计算精度问题

    本文讲解的是怎么实现一个工具库并打包发布到npm给大家使用.本文实现的工具是一个分数计算器,大家考虑如下情况: \[ \sqrt{(((\frac{1}{3}+3.5)*\frac{2}{9}-\fr ...

  6. java中浮点数的比较(double, float)(转)

    问题的提出:如果我们编译运行下面这个程序会看到什么? public static void main(String args[]){ System.out.println(0.05+0.01); Sy ...

  7. 最全的Java操作Redis的工具类,使用StringRedisTemplate实现,封装了对Redis五种基本类型的各种操作!

    转载自:https://github.com/whvcse/RedisUtil 代码 ProtoStuffSerializerUtil.java import java.io.ByteArrayInp ...

  8. 常用 Java 静态代码分析工具的分析与比较

    常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...

  9. [原创]Java静态代码检查工具介绍

    [原创]Java静态代码检查工具介绍 一  什么是静态代码检查? 静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法.结构.过程.接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数 ...

随机推荐

  1. 渗透测试--Nmap主机识别

    通过本篇博客可以学到:Nmap的安装和使用,列举远程机器服务端口,识别目标机器上的服务,指纹,发现局域网中存活主机,端口探测技巧,NSE脚本使用,使用特定网卡进行检测,对比扫描结果ndiff,可视化N ...

  2. 关于 JMeter 5.4.1 的一点记录

    APACHE JMeter table { border: 0; border-collapse: collapse; background-color: rgba(255, 245, 218, 1) ...

  3. 小心你的个人信息——GitHub 热点速览 v.21.09

    作者:HelloGitHub-小鱼干 浏览过必有痕迹,有什么可以抹去社交痕迹的方法呢?social-analyzer 是一个可在 350+ 网站分析特定用户资料的工具,你可以用它来"人肉&q ...

  4. 如何读写拥有命名空间xmlns 属性的Xml文件(C#实现)

    我们在进行C#项目Xml读写开发时经常遇到一些读写问题,今天我要介绍的是遇到多个命名空间xmlns属性时如何读写此类文件. 比如下面这个Xml文件: <?xml version="1. ...

  5. 防数据泄露_MySQL库和数据安全

    目录 攻击场景 外部入侵 内部盗取 防御体系建设 参考 在企业安全建设中有一个方向是防数据泄露,其中一块工作就是保障数据库安全,毕竟这里是数据的源头.当然数据库也分不同的种类,不同类型的数据库的防护手 ...

  6. POJ-1087(最大流+EK算法)

    A Plug for UNIX POJ-1087 这一题也是最大流的应用,但是题目有点绕. 题目的意思就是有插座和插头,只不过这里使用设备取代了插头.只有插座和设备进行匹配了. 题目要注意的是那个适配 ...

  7. 恭喜!Apache Hudi社区新晋两位Committer

    1. 介绍 经过Apache Hudi项目委员会讨论及投票,向WangXiangHu和LiWei 2人发出Committer邀请,2人均已接受邀请并顺利成为Committer,也使得Apache Hu ...

  8. 爬虫必知必会(7)_scrapy框架高级

    一.请求传参 实现深度爬取:爬取多个层级对应的页面数据 使用场景:爬取的数据没有在同一张页面中 在手动请求的时候传递item:yield scrapy.Request(url,callback,met ...

  9. HDU(1420)Prepared for New Acmer(JAVA语言)【快速幂模板】

    思路:快速幂裸题. //注意用long,否则会超范围 Problem Description 集训进行了将近2个礼拜,这段时间以恢复性训练为主,我一直在密切关注大家的训练情况,目前为止,对大家的表现相 ...

  10. java例题_46 两个字符串拼接问题!

    1 /*46 [程序 46 字符串连接] 2 题目:两个字符串连接程序,将两个字符串拼接在一起 3 */ 4 5 /*分析 6 * 两个字符串的拼接方法 7 * concat方式 8 * 当两个量都为 ...