[20191104]数值累加的各种方法3.txt
--//前一阵子做了数值累加的测试,
--//链接如下:
http://blog.itpub.net/267265/viewspace-2660877/=>[20191021]数值累加的各种方法.txt
http://blog.itpub.net/267265/viewspace-2661719/=>[20191028]数值累加的各种方法2.txt
--//如果记录很多是不可能拼接成1行来实现累计的,比如:
$ seq 1000000 | paste -sd+ | bc
(standard_in) 1: parse error
--//本次测试看看大量累加选择何种方式最快!!
1.建立测试脚本:
set pagesize 0
spool aa.txt
select AMOUNT_SOLD from sh.sales;
spool off
SCOTT@book> select sum(AMOUNT_SOLD),count(*) from sh.sales;
SUM(AMOUNT_SOLD) COUNT(*)
---------------- ----------
98205831.2 918843
--//适当编辑aa.txt文本,删除开头以及结尾的非数字信息.
$ wc aa.txt
918843 918843 11026116 aa.txt
$ paste -sd+ aa.txt | bc
98205831.21
$ paste -sd+ aa.txt | bc -l
98205831.21
--//奇怪什么会有累计误差呢?先不管这个问题.
$ awk '{sum+=$1} END {printf("%.10f\n",sum)}' aa.txt
98205831.2100249678
$ seq 100 | xargs -I {} cat aa.txt >> aaa.txt
$ wc aaa.txt
91884300 91884300 1102611600 aaa.txt
--//数据量扩大100倍.
2.测试:
--//奇怪这样也可以执行,为什么seq 1000000 | paste -sd+ | bc有问题呢?
$ time paste -sd+ aaa.txt | bc -l
9820583121.00
real 0m56.056s
user 0m58.227s
sys 0m2.145s
$ time awk '{sum+=$1} END {printf("%.10f\n",sum)}' aaa.txt
9820583120.8551120758
real 0m43.603s
user 0m43.135s
sys 0m0.371s
--//awk在做累计计算是存在误差!!
$ time cat aaa.txt |xargs | sed 's/ /+/g' | paste -sd+ | bc
9820583121.00
real 1m6.532s
user 2m25.466s
sys 0m26.889s
--//dc计算太慢,我估计那串 -e '[+z1<r]srz1<rp',是判断是否栈内还有数据,每次判断浪费许多时间.
$ time seq 100000 | dc -f - -e '[+z1<r]srz1<rp'
Segmentation fault
real 0m13.743s
user 0m13.786s
sys 0m0.036s
--//100000条就需要13秒.就是aa.txt文本918843条(增加9倍),时间也是很长的.也就是dc仅仅合适数据比较少的情况.
--//可以看出最快awk,但是累计计算存在误差,不推荐使用.还是paste -sd+加bc模式比较好.
3.为什么bc计算存在偏差呢?
$ cat a.sql
set head off pagesize 0 feedback off verify off echo off
set term off
spool bb.txt
select AMOUNT_SOLD from sh.sales;
spool off
set term on
SCOTT@book> @ a.sql
$ wc bb.txt aa.txt
918843 918843 11026116 bb.txt
918843 918843 11026116 aa.txt
1837686 1837686 22052232 total
$ diff aa.txt bb.txt
$ paste -sd+ bb.txt | bc -l
98205831.21
--//没有问题啊.我在toad下测试,结果正常.
select sum(AMOUNT_SOLD),count(*) from sh.sales;
--//实际上问题在sqlplus显示数字的处理方式上.在sqlplus下执行如下就很清楚了.
SCOTT@book> select 98205831.21 , 8205831.21 from dual ;
98205831.21 8205831.21
----------- ----------
98205831.2 8205831.21
--//仔细看了以前的链接:http://blog.itpub.net/267265/viewspace-2284458/=>[20181207]sqlplus下显示数据精度.txt
--//没有想到自己还犯了一个严重错误.另外写一篇文章说明这个问题.
--//可以看出bc计算是正确的,问题在与sqlplus下显示数据问题.
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2662466/ ,如需转载,请注明出处,否则将追究法律责任。