说起编程中的高精度数值,我第一反应就是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. Excel小技巧之VLOOKUP()使用简单说明

    前两天人事的小姐姐需要处理一个表格,需要在一张新表中的匹配旧表的数据,由于数据量较大不知如何处理. 我告诉她使用VLOOKUP()函数,然后她不知道怎么使用.其实我也不大用,因为数据库用的多很少使用表 ...

  2. 为什么数据库能查出两条id相同的数据

    sql如下: SELECT t.*,d.name as "workName" FROM t_traceability_slice t LEFT JOIN sys_departmen ...

  3. iframe页面刷新

    //方法1 document.getElementById('FrameID').contentWindow.location.reload(true); //方法2 document.getElem ...

  4. 关于Java高并发编程你需要知道的“升段攻略”

    关于Java高并发编程你需要知道的"升段攻略" 基础 Thread对象调用start()方法包含的步骤 通过jvm告诉操作系统创建Thread 操作系统开辟内存并使用Windows ...

  5. 解决浏览器点击button出现边框问题

    发现问题 本人不懂浏览器的HTML代码 不知道怎么在chrome浏览器的F12之后点到了哪里 点击button的时候就会出现黑色边框 解决 终于发现不是因为动了调试页面,而是动了谷歌浏览器的高级选项, ...

  6. mysql内一些可以报错注入的查询语句

        一.exp() 取反参数 该函数简单来说就是,以e为底的对数,在当传递一个大于709的值时,函数exp()就会引起一个溢出错误,取反则可以导致很小的数值变得很大,比如说0 这样既可配合使用,e ...

  7. 基于Linux的tty架构及UART驱动详解

    更多嵌入式Linux原创,请关注公众号:一口Linux 一.模块硬件学习 1.1. Uart介绍 通用异步收发传输器(Universal Asynchronous Receiver/Transmitt ...

  8. 混合编程:如何用python11调用C++

    摘要:在实际开发过程中,免不了涉及到混合编程,比如,对于python这种脚本语言,性能还是有限的,在一些对性能要求高的情景下面,还是需要使用c/c++来完成. 那怎样做呢?我们能使用pybind11作 ...

  9. 操作系统实验(一)-Shell编程

    操作系统实验:Shell编程 emmmmm,实验前老师发了一份实验说明,里面有教怎么配置虚拟机Ubuntu.这里就不做过多叙述,需要说明的是,kali和ubuntu都可以以shell运行这个C语言程序 ...

  10. Powerful Number 筛学习笔记

    Powerful Number 筛学习笔记 用途 \(Powerful\ number\) 筛可以用来求出一类积性函数的前缀和,最快可以达到根号复杂度. 实现 \(Powerful\ number\) ...