python高精度 您所在的位置:网站首页 全民一起vba提高篇第二十三回 python高精度

python高精度

2023-11-18 19:33| 来源: 网络整理| 查看: 265

大家好,我们今早已经发布了《全民一起玩Python》第七回“逻辑运算可以巧写代码,数据读写需要区分类型”。课堂笔记已经可以在官网 www.ukoedu.com 浏览,补充阅读资料和习题明天上传。

这节课的主要内容分为上下两部分:

前半节首先介绍了怎样用整数代替小数执行计算,从而利用 Python 中整数无溢出的特点实现高精度计算;然后我们通过一个比较形象(但并不精确)的方式,为大家介绍了这几节课经常提到的“浮点数”的基本原理,也就是一种特殊的二进制“科学计数法”。

702adb6ca3f7d24b86db8bd9291b0d34.png

后半节中,我们首先介绍了 Python 中的数据类型,然后重点讲解逻辑类型的运算规则和应用技巧,包括逻辑运算、关系运算、简化循环判断表达式、实现正负切换等内容。

上述知识大家只要认真看视频就可以理解(本节课屏幕板书较多,请大家在听讲的同时也留意文字、必要时暂停播放)。需要特别注意的是学完这节课之后,各位就要开始习惯把下面左侧的写法改成右侧写法,以便表现出更加(you)专(bi)业(ge)的样子:

df8b841de86ff6ddb74e31ab30e5474e.png

话说在做完这几节有关数字的章节后,杨老师又回头看了一遍《全民一起VBA 提高篇》关于数据类型的几节课,不由得深深感慨两件事:1. VBA 的数据类型与Python差别真大!2. 两年前我们的样子好土!

6bd4a1b88dcb944b20ae958149d2623f.png

可以说从基本数据类型的角度看,VBA 与 Python 明显代表了两个年代。虽然二者都是以简化学习难度、方便用户编程为特色,但是VBA的数据类型明显还是与传统语言如C、Java等一脉相承,比如把整数分为 Byte(1字节长度)、Integer(2字节长度)、Long(4字节长度)、把浮点数分为 Single(4字节长度)和 Double (8字节长度)等。

相比之下,Python 直接简单干脆的把数字分为整数、小数和复数,与我们在中小学数学教材里看到的一模一样,不了解字节等计算机术语也一样能理解。而更令人开心的是,整数根本不限制字节长度,有多少内存就能放多大整数(见 Python提高篇 上节课内容)。也正是出于这个原因,我们这节课程里才能使用“整数替代小数”的技巧实现精确的小数计算。

但是对于 VBA 来说,同样的问题该怎样解决呢?比如我们在这节课中使用的例子 1.23456789 * 9.87654321 ,在 Python 中直接运算会产生截断误差:

9f1e003bac8b0327520684422c82b32f.png

而对于同样的问题,在VBA中直接运算也会产生完全一样的误差,因为 VBA 默认也是采用 64 位浮点数(Double类型)存放小数的:

8e7cecde9ecab744707efb3b61079672.png

但是问题在于,Python 中可以利用其整数无溢出的特点,直接计算整数乘法再进行转换,就像本节课视频中演示的那样。但是在 VBA 中,即使长整型(Long)也只有 4 个字节大小,甚至其特有的货币类型(Currency)也只有 8 个字节,都一样存在溢出问题,因而不能用来解决小数精度问题。

f00d7f7ab4c3e1b106855ecf0464be30.png类型,但是

所以对于VBA中的高精度小数计算,最简单的办法就是使用一个特殊的数据类型:Decimal (类似Python中的Decimal类)。我们在《全民一起VBA  提高篇》里只是提到过这个类型,但好像没有详细介绍其用法。

首先,Decimal 类型使用 12 个字节存放数字,具体采用的也是类似于“科学计数法”的形式,算是一种特殊的浮点数。所以它能够存储的数字范围显著大于其他几种类型,比如当整数位只有一位数字时,它可以实现小数点后28位的精度。

其次,在程序中不能把变量直接声明为Decimal类型!我们必须使用 CDec( ) 函数才能创造出一个 Decimal 类型的数值,而如果想把该数值赋给某个变量,这个变量必须是变体类型,否则会出现截断误差。

因此对于 1.23456789 * 9.87654321 这个问题,我们就可以用下面的代码来解决:

5448a4c4c3c15ee4b0aa5f1be5d63948.png

甚至可以实现更高小数位数的精确计算,比如下面的算式(计算结果共含26位小数):

4ba92bc098c4564e277bcd57e06a97d4.png

处理Long类型无法应付的大整数也没有问题:

ffb121fa45787c6b19e125306ccb6cd5.png

不过还是要注意:毕竟 Decimal 也不是无限内存、只能使用12个字节,所以太大的数字还是会导致截断误差,比如下面的计算结果中,尾数显然不正确:

3b22c2fc7ee892d126b679fb916035ef.png

那么对于更大的数字该怎么办呢?这就需要我们自己把人类计算乘法(就是小学时学过的竖式乘法)规则编为程序,然后按照以下步骤处理:

把两个需要相乘的超大数字分别以字符串形式保存

使用字符串函数,在两个字符串中从后向前读取一个字符

用 CInt函数  把读出的字符转换为整数并相乘

用自己编写的乘法进位程序,将相乘的结果记录下来、需要进位就进位

如此反复,直到使用竖式乘法规则把所有步骤都完成,得到最终结果(也是一个字符串)。

具体大家如果有兴趣,上网随便找一下中小学生计算机竞赛题就可以(不好意思,扎心了 …… )

祝大家学习愉快!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有