说起编程中的高精度数值,我第一反应就是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. 简单比较 @EnableEurekaClient 和 @EnableDiscoveryClient 两个注解

    @EnableEurekaClient 和 @EnableDiscoveryClient 都是让eureka发现该服务并注册到eureka的注解 相同点: 它们都能让注册中心Eureka发现 , 并将 ...

  2. Android - 利用扩展函数为Bitmap添加文字水印

    <异空间>项目技术分享系列--扩展函数为Bitmap添加文字水印 对图片Bitmap绘制文字水印还是比较常见的需求,毕竟版权意识都在增强(用户可以给自己图片加上用户名),还可以为用户提供更 ...

  3. Win10下ctrl与alt键互换

    我之前尝试过用第三方软件修改,但是总是不成功,后来发现直接去修改注册表也不麻烦,记录一下步骤. win + r 输入 regedit 进到这个路径 点击Keyboard Layout 右键,新建一个 ...

  4. iOS 14.5 有啥新功能?Apple Watch 也能解锁 iPhone 了

    转: iOS 14.5 有啥新功能?Apple Watch 也能解锁 iPhone 了 苹果今天发布了即将发布的 iOS 14.5 和 iPadOS 14.5 更新的第一个 Beta 版本,我们在其中 ...

  5. 利用CORDIC算法计算三角函数

    这里主要先介绍如何利用CORDIC算法计算固定角度\(\phi\)的\(cos(\phi)\).\(sin(\phi)\)值.参考了这两篇文章[1].[2]. 一般利用MATLAB计算三角函数时,用\ ...

  6. React开发入门:以开发Todo List为例

    目录 概述 React基本概念 JSX是什么? 设置React APP 初始化APP 应用结构 探索第一个React组件 index.js 变量和props JSX中的变量 组件props props ...

  7. Elastic App Search 快速构建 ES 应用

    公号:码农充电站pro 主页:https://codeshellme.github.io App Search 是 Elastic 家族中的一个产品,它可以帮助我们(基于 ES)快速高效的构建搜索应用 ...

  8. 剑指 Offer 14- I. 剪绳子 + 动态规划 + 数论

    剑指 Offer 14- I. 剪绳子 题目链接 还是343. 整数拆分的官方题解写的更清楚 本题说的将绳子剪成m段,m是大于1的任意一个正整数,也就是必须剪这个绳子,至于剪成几段,每一段多长,才能使 ...

  9. CentOS 7关闭firewalld启用iptables 开放端口

    在CentOS7中,有很多CentOS 6中的常用服务发生了变化. 其中iptables是其中比较大的一个.防火墙iptables被firewalld取代. 本文将介绍,如果采用systemctl关闭 ...

  10. js--this指向的相关问题

    前言 关于this的指向问题是前端面试中常考的知识点,也是我们开发学习中较难理解的问题.作为JavaScript的基础,需要我们彻底理解这一关键词.this作为JavaScript中非常复复杂的机制, ...