简析水文数据的收舍以及在编程中的实现

2021-12-27 06:50施艺
四川水利 2021年6期
关键词:位数水文小数

施艺

(四川省成都水文水资源勘测局,成都,611130)

1 引言

水文数据是国家重要的基础信息资源,而水文工作则是行业基础数据的主要来源。为保证水文资料成果质量,《水文资料整编规范》(SL/T 247-2012)对水文数据中各项要素计算、取用精度做出了要求:各项要素数值应按规范要求的取用精度取位,取用精度位数后一位数字,采用“四舍六入”方法取舍。为更好地适应水文信息化和现代化发展,本文对水文数据的收舍以及在编程中的实现进行了分析探讨。

2 水文数据的收舍

2.1 有效数字

有效数字(Significant Figure),是在整个计算过程中大致维持重要性的近似规则。对于一个近似数,从左边第一个非零数字起,到精确到的位数止,所有的数字都叫作这个数的有效数字。简单地说,把一个数字前面的0都去掉,从第一个正整数到精确的数为止所有的数字都是有效数字。

在水文数据中,各项要素数值的取用精度多采用“有效数字+小数不过多少位”的方式进行取位,如流量、比降、输沙率采用“3位有效数字,小数不过3位”,洪水量、径流量采用“4位有效数字,小数不过4位”。取用精度位数后一位数字,采用“四舍六入”方法取舍。

2.2 四舍六入

四舍六入,全称四舍六入五成双,是一种比较精确、比较科学的计数保留法。具体规则为取用精度位数后1位小数小于5则舍,大于5则入,等于5时若其后有非零位数仍入,无非零尾数则视取用的末位数字的奇偶取舍,为奇则入,为偶则舍。

在国外,四舍六入又被称为Banker's round(即银行家舍入),大部分的编程软件都使用的是这种方法,但具体到大家日常使用的办公软件却很少使用四舍六入,基本都是四舍五入。比如EXCEL里的Round函数采用的是四舍五入,而VBA中的Round函数则采用的是四舍六入。

3 在编程中的实现

3.1 实现的意义

前文提到,日常使用的办公软件如OFFICE、WPS等基本都是采用四舍五入,无法满足水文数据的收舍要求。如在EXCEL中,Round函数采用的是四舍五入,如果想要四舍六入,需要通过设置复杂的公式,即便通过公式能达到目的,也需要针对性地设置数值相应的收舍位数,对每个值进行单独设置,工作量很大,也很繁琐。在编程中实现水文数据的收舍,既能为进一步开发水文相关的软件提供支撑,同样也能通过与现有办公软件相结合,扩展现有办公软件的使用局限,方便普通职工的使用。

限于会占用大量篇幅,文章只采用了一到两种语言来进行介绍,虽然不同语言的代码格式不同,但思路是通用的。

3.2 实现的方法

3.2.1 有效数字的实现

在常用的编程语言中,除C++不支持Banker's round(即四舍六入)外,其余常用的编程语言都使用四舍六入。按有效数字进行收舍则只有C++可以通过setprecision函数以及R语言可以通过signif函数可以做到。要按有效数字进行四舍六入,可以通过封装自定义函数来实现。

实现思路为:设数值为i,有效数字为d,数值的位数为k。先判断数值i的位数k,大于1时k为正,取i整数部分位数;小于1时k为负,取i小数点后出现多少个连续的零。d减去k,得到需要收舍的位数n。按round(i,n)对数值i进行四舍六入。

遇到的问题1:n为负时round函数无法工作,即收舍只能对数值的小数部分进行收舍,无法根据有效数字对整数部分进行收舍,如12850的3位有效数字应收舍为12800。解决方案:对数值乘以10的n次方,然后按取整进行四舍六入,再除以10的n次方,这样就能对整数部分也进行有效数字的收舍了。

遇到的问题2:判断数值i的位数k,开始是用字符串进行处理,方法为如果i大于1,取i小数点左边的字符串的长度;如果i小于1,取i小数点右边数值的长度减去i小数点右边字符串的长度。如0.0012小数点右边字符串为0012、字符串长度为4,而0012的值为12、字符串长度为2,2减去4就得出i的位数k为-2。但这样处理代码效率不高,影响大量数据处理的效率。解决方案:经过翻阅资料,发现一个小技巧,通过对数值(绝对值)求其以10为底的对数,可以很方便地知道它的位数。如log10(0.0012)等于-2.9,向上取整后即为数值i的位数-2,log10(6554)等于3.8,向上取整后即为数值i的位数4。

以Java语言为例,实现代码如下。

为方便普通职工在EXCEL中直接使用该函数,接下来采用VBA语言进行编译,将函数封装为自定义公式,实现代码如下。

采用VBA语言进行编译需要注意的是:①EXCEL中默认采用的是浮点数运算,由于计算机在处理数据时存在二进制与十进制的转换,直接对数值进行处理往往会出错,需要通过CDec函数将数值转换为Decimal类型数据再进行处理;②VBA中没有log10函数,也没有向上取整,我们通过Log(i)/Log(10)来代替log10函数,再通过Int(i)+1计算得到位数。

3.2.2 水文数据收舍的实现

水文数据的收舍,不仅需要满足按有效数字进行四舍六入,还要按不超过多少位小数进行收舍。因此,还需要对自定义函数进行加工。

实现思路为:设置可选项最大小数位数d1,默认为0(不设置最大小数位数),可选项有效数字d2,默认为0(不设置有效数字)。当有效数字大于0,如果最大小数位数d1不小于有效数字d2减去数值i的位数k,需要收舍的位数n则为d2减去k,否则n等于最大小数位数d1。其余步骤参考之前代码。为方便在其他代码中调用该函数(下文会有介绍),可以设置全局变量Ⅳalue、iDigits,将收舍后的值赋予Ⅳalue、收舍的位数赋予iDigits。

以VBA语言为例,实现代码如下。

3.3 进阶运用

3.3.1 复合条件的应用

在水文数据的计算中,除了按有效数字以及最大小数位数进行四舍六入,某些要素数值是通过复合条件确定取用精度。比如流速为数值不小于1取3位有效数字,小于1取2位有效数字,小数不过3位;水深为数值不小于100记至1,小于100不小于5记至0.1,小于5记至0.01。针对这样的情况,可以对自定义函数进行再开发,通过设定具体的要素类型,对数值进行处理。接下来的代码演示以下5种类型的取用精度及运算。

类型1:取3位有效数字,小数不过3位。如流量、径流模数、输沙率等。

类型2:取3位有效数字,小数不过2位。如断面面积、流量系数等。

类型3:不小于1,取3位有效数字;小于1,取2位有效数字,小数不过3位。如流速。

类型4:不小于100,记至1;小于100,不小于5,记至0.1;小于5,记至0.01。如水深。

类型5:取3位有效数字;不小于5,小数不过1位;小于5,小数不过2位。如水面宽、闸门开启总宽、平均堰宽等。

3.3.2 按刊印要求进行设置

在水文资料整编中,除了对数值的精度有要求,对数据的刊印格式也有同样的要求,通过调用自定义函数可以方便我们对数据进行处理。以下代码用于在表格保存时对表格中的数值按刊印要求进行位数的设置。

代码解析:首先,将有数字的单元格设置为一个Range对象,遍历这些单元格,根据单元格所在的位置将其设置为对应的类型,比如表格中第三列是水深数据、第四列是面积、第五列是流速、第六列是流量,将第三列设为类型4、第四列设为类型2、第五列设为类型3、第六列设为类型1;其次,通过调用Sw_Round函数,判断数值是否满足相应类型的取用精度,不满足则更改为收舍后满足取用精度的值,比如流量10.25应改为10.2;最后,根据Sw_Round函数得到的数值应该保留的位数,将其设置为对应格式比如流速0.5应写为0.50。

4 结语

本文简要介绍了通过程序语言封装自定义函数实现水文数据的收舍,以及对相关函数的扩展应用,为进一步开发水文相关软件提供一定的支撑,同样也能通过与现有办公软件相结合方便普通职工使用。以期解决以往遇到收舍与刊印要求时单个要求单个处理,缺乏可移植性,重复工作量大以及数据处理缺乏可靠性的问题。当然,这只是笔者的一点经验之谈,旨在抛砖引玉,希望能让更多的专业技术人员受到启发,将编程更多地应用到水文信息化建设中。

猜你喜欢
位数水文小数
小数加减“四不忘”
继往开来 守正创新——河北省水文工程地质勘查院
我国古代的小数
小数的认识
小数的认识
继往开来 守正创新——河北省水文工程地质勘查院
连续自然数及其乘积的位数分析
水文
水文水资源管理
比大小有窍门