python高精度 | 您所在的位置:网站首页 › 全民一起vba提高篇第二十三回 › python高精度 |
大家好,我们今早已经发布了《全民一起玩Python》第七回“逻辑运算可以巧写代码,数据读写需要区分类型”。课堂笔记已经可以在官网 www.ukoedu.com 浏览,补充阅读资料和习题明天上传。 这节课的主要内容分为上下两部分: 前半节首先介绍了怎样用整数代替小数执行计算,从而利用 Python 中整数无溢出的特点实现高精度计算;然后我们通过一个比较形象(但并不精确)的方式,为大家介绍了这几节课经常提到的“浮点数”的基本原理,也就是一种特殊的二进制“科学计数法”。 后半节中,我们首先介绍了 Python 中的数据类型,然后重点讲解逻辑类型的运算规则和应用技巧,包括逻辑运算、关系运算、简化循环判断表达式、实现正负切换等内容。 上述知识大家只要认真看视频就可以理解(本节课屏幕板书较多,请大家在听讲的同时也留意文字、必要时暂停播放)。需要特别注意的是学完这节课之后,各位就要开始习惯把下面左侧的写法改成右侧写法,以便表现出更加(you)专(bi)业(ge)的样子: 话说在做完这几节有关数字的章节后,杨老师又回头看了一遍《全民一起VBA 提高篇》关于数据类型的几节课,不由得深深感慨两件事:1. VBA 的数据类型与Python差别真大!2. 两年前我们的样子好土! 可以说从基本数据类型的角度看,VBA 与 Python 明显代表了两个年代。虽然二者都是以简化学习难度、方便用户编程为特色,但是VBA的数据类型明显还是与传统语言如C、Java等一脉相承,比如把整数分为 Byte(1字节长度)、Integer(2字节长度)、Long(4字节长度)、把浮点数分为 Single(4字节长度)和 Double (8字节长度)等。 相比之下,Python 直接简单干脆的把数字分为整数、小数和复数,与我们在中小学数学教材里看到的一模一样,不了解字节等计算机术语也一样能理解。而更令人开心的是,整数根本不限制字节长度,有多少内存就能放多大整数(见 Python提高篇 上节课内容)。也正是出于这个原因,我们这节课程里才能使用“整数替代小数”的技巧实现精确的小数计算。 但是对于 VBA 来说,同样的问题该怎样解决呢?比如我们在这节课中使用的例子 1.23456789 * 9.87654321 ,在 Python 中直接运算会产生截断误差: 而对于同样的问题,在VBA中直接运算也会产生完全一样的误差,因为 VBA 默认也是采用 64 位浮点数(Double类型)存放小数的: 但是问题在于,Python 中可以利用其整数无溢出的特点,直接计算整数乘法再进行转换,就像本节课视频中演示的那样。但是在 VBA 中,即使长整型(Long)也只有 4 个字节大小,甚至其特有的货币类型(Currency)也只有 8 个字节,都一样存在溢出问题,因而不能用来解决小数精度问题。
所以对于VBA中的高精度小数计算,最简单的办法就是使用一个特殊的数据类型:Decimal (类似Python中的Decimal类)。我们在《全民一起VBA 提高篇》里只是提到过这个类型,但好像没有详细介绍其用法。 首先,Decimal 类型使用 12 个字节存放数字,具体采用的也是类似于“科学计数法”的形式,算是一种特殊的浮点数。所以它能够存储的数字范围显著大于其他几种类型,比如当整数位只有一位数字时,它可以实现小数点后28位的精度。 其次,在程序中不能把变量直接声明为Decimal类型!我们必须使用 CDec( ) 函数才能创造出一个 Decimal 类型的数值,而如果想把该数值赋给某个变量,这个变量必须是变体类型,否则会出现截断误差。 因此对于 1.23456789 * 9.87654321 这个问题,我们就可以用下面的代码来解决: 甚至可以实现更高小数位数的精确计算,比如下面的算式(计算结果共含26位小数): 处理Long类型无法应付的大整数也没有问题: 不过还是要注意:毕竟 Decimal 也不是无限内存、只能使用12个字节,所以太大的数字还是会导致截断误差,比如下面的计算结果中,尾数显然不正确: 那么对于更大的数字该怎么办呢?这就需要我们自己把人类计算乘法(就是小学时学过的竖式乘法)规则编为程序,然后按照以下步骤处理: 把两个需要相乘的超大数字分别以字符串形式保存 使用字符串函数,在两个字符串中从后向前读取一个字符 用 CInt函数 把读出的字符转换为整数并相乘 用自己编写的乘法进位程序,将相乘的结果记录下来、需要进位就进位 如此反复,直到使用竖式乘法规则把所有步骤都完成,得到最终结果(也是一个字符串)。 具体大家如果有兴趣,上网随便找一下中小学生计算机竞赛题就可以(不好意思,扎心了 …… ) 祝大家学习愉快! |
CopyRight 2018-2019 实验室设备网 版权所有 |