Abstract:This article gives a computer-defined function, descriptive the design mentality and the source code of the function process, expounds this method simplicity, versatility, easy operational and reliability, and introduce its service condition unified the application example.
Keywords:hydrological data;time interpolation;time average;function;example
摘 要: 本文給出一個(gè)計(jì)算機(jī)自定義函數(shù),敘述了該函數(shù)過(guò)程的設(shè)計(jì)思路和源程序代碼,闡明了此方法的簡(jiǎn)單性、通用性、易操作性和可靠性,并結(jié)合應(yīng)用實(shí)例介紹了其使用情況。
關(guān)鍵詞: 水文資料 時(shí)間差值和均值 函數(shù) 舉例
中圖分類(lèi)號(hào):O174 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):
1問(wèn)題的提出
在工作實(shí)踐中,經(jīng)常需要我們對(duì)一個(gè)時(shí)間段進(jìn)行各類(lèi)操作,比如計(jì)算兩個(gè)時(shí)間的歷時(shí)即差值,兩個(gè)時(shí)間的中間時(shí)間即均值。如果該差值是很小的,不難由人工直接計(jì)算這兩項(xiàng)數(shù)據(jù),而在計(jì)算機(jī)進(jìn)行運(yùn)算和管理時(shí)卻變成了一個(gè)復(fù)雜的過(guò)程。因?yàn)椋@兩個(gè)時(shí)間往往都是日期-時(shí)間型數(shù)據(jù),各類(lèi)軟件開(kāi)發(fā)工具均未能直接給出它們的關(guān)系運(yùn)算函數(shù),或只是對(duì)日期和時(shí)間分別給出簡(jiǎn)單的運(yùn)算,實(shí)踐中遇到的跨日、跨月甚至跨年度的時(shí)間段的處理會(huì)給我們帶來(lái)更大難度。從水文測(cè)驗(yàn)過(guò)程到水情拍報(bào)乃至資料整編,都常常遇到這一問(wèn)題,給計(jì)算機(jī)處理帶來(lái)極大的不便。為此,筆者經(jīng)過(guò)摸索和反復(fù)驗(yàn)證,給出一個(gè)成熟可靠的自定義函數(shù),調(diào)入計(jì)算機(jī)內(nèi)存后便可靈活地對(duì)任意兩個(gè)日期——時(shí)間型數(shù)據(jù)進(jìn)行操作。
2自定義函數(shù)的設(shè)計(jì)
2.1設(shè)計(jì)思路
構(gòu)造該函數(shù)過(guò)程,按不同的參數(shù)返回(Return)兩個(gè)不同結(jié)果,即時(shí)間差值和均值。該函數(shù)有5個(gè)參數(shù),分別設(shè)定為第一時(shí)間的日期和時(shí)分dat1和tim1、第二時(shí)間的日期和時(shí)分dat2和tim2 ,控制函數(shù)返回差值或均值參數(shù)cs(Integer型),取1或0 ,于是給出函數(shù)型式Op_DateTime(dat1,tim1,dat2,tim2,cs)。比較出兩個(gè)日期-時(shí)間型數(shù)據(jù)的較小者,提取其中的年份并以該年份的1月1日00:00時(shí)為參照時(shí)間,如此就會(huì)最簡(jiǎn)單地使用系統(tǒng)函數(shù)計(jì)算出兩個(gè)時(shí)間分別同這一參照時(shí)間的差值,換算為分鐘,則這兩個(gè)差值的差即為所求差值。將該差值除以2,按年月日時(shí)規(guī)則,通過(guò)循環(huán)數(shù)據(jù)結(jié)構(gòu)控制累加到第一時(shí)間,即為所求均值。
2.2函數(shù)源代碼(PowerScript腳本)
//函數(shù)形式 Op_DateTime(dat1,tim1,dat2,tim2,cs)
//返回值jisuan_date_time為 String 型
//dat1、dat2為Date型,tim1、tim2為T(mén)ime型, cs為Integer 型
//cs = 1函數(shù)返回差值,否則返回均值
//下面聲明程序使用的變量,考慮分鐘等數(shù)值過(guò)大,盡量使用Long和Decimal型
Date dat,dat0
Time tim
Long tianshu1,tianshu2,ztime,xiaoshi,yue,tian,shi,fen
Long jisuan_d jisuan_m,jisuan_y,i,m_2
Dec fenzhong
String jisuan_date_time = ""
//如果給定的第一時(shí)間大于第二時(shí)間,則交換一下位置
IF DateTime(dat1,tim1) > DateTime(dat2,tim2) THEN
dat = dat1
dat1 = dat2
dat2 = dat
tim = tim1
tim1 = tim2
tim2 = tim
END IF
dat0 = Date(Year(dat1),1,1) //虛擬第一時(shí)間年份的1月1日00:00時(shí)做參照時(shí)間
tianshu1 = DaysAfter(dat0,dat1) //取得第一時(shí)間同參照時(shí)間的之間的天數(shù)
tianshu2 = DaysAfter(dat0,dat2) //取得第二時(shí)間同參照時(shí)間的之間的天數(shù)
//計(jì)算兩個(gè)時(shí)間之間總分鐘數(shù)
ztime = tianshu2 * 1440 + Hour(tim2) * 60 + Minute(tim2)
ztime = ztime - (tianshu1 * 1440 + Hour(tim1) * 60 + Minute(tim1))
IF cs = 1 THEN
jisuan_date_time = String(Ztime) //得到參數(shù)為1時(shí)的時(shí)間間隔(分鐘,String型)
ELSE //參數(shù)不為1時(shí),推算兩個(gè)時(shí)間的中值或叫均值
jisuan_d = Day(dat1) //得到第一時(shí)間中的天數(shù)
jisuan_m = Month(dat1) //得到第一時(shí)間中的月份
jisuan_y = Year(dat1) //得到第一時(shí)間中的年度
fenzhong = Minute(tim1) + Ztime/2
i = 0
DO UNTIL fenzhong <= 32766 //將分鐘變得足夠小,以便下邊能取Integer
fenzhong = fenzhong - 32766 //并要保證分鐘整數(shù)部分原有的奇和偶
i = i + 1
LOOP
IF fenzhong > Int(fenzhong) THEN //考慮逢5奇進(jìn)偶舍
IF Int(fenzhong)/2 = Int(Int(fenzhong)/2) THEN
fenzhong = Int(fenzhong)
ELSE
fenzhong = Int(fenzhong) + 1
END IF
END IF
fenzhong = fenzhong + 32766 * i
fen = Mod(fenzhong,60) //取余數(shù)得到平均時(shí)間的分鐘值
xiaoshi = Int(fenzhong/60) + Hour(tim1)
shi = Mod(Dec(xiaoshi),24) //取余數(shù)得到平均時(shí)間的小時(shí)值
tian = Int(xiaoshi/24) //取整數(shù)得到進(jìn)位的天數(shù)
IF tian > 0 THEN
FOR i = 1 TO tian //按不同的月份和年份逐日進(jìn)位
CHOOSE CASE jisuan_m
CASE 1,3,5,7,8,10,12
IF jisuan_d < 31 THEN
jisuan_d = jisuan_d + 1
ELSE
jisuan_d = 1
IF jisuan_m = 12 THEN
jisuan_m = 1
jisuan_y = jisuan_y + 1
ELSE
jisuan_m = jisuan_m + 1
END IF
END IF
CASE 2
IF jisuan_y = Int(jisuan_y/4) * 4 THEN //考慮閏年情況
m_2 = 29
ELSE
m_2 = 28
END IF
IF jisuan_d < m_2 THEN
jisuan_d = jisuan_d + 1
ELSE
jisuan_d = 1
jisuan_m = jisuan_m + 1
END IF
CASE ELSE
IF jisuan_d < 30 THEN
jisuan_d = jisuan_d + 1
ELSE
jisuan_d = 1
jisuan_m = jisuan_m + 1
END IF
END CHOOSE
NEXT
END IF
//按yyyy-mm-dd hh:mm格式計(jì)算取得平均時(shí)間結(jié)果,String型
jisuan_date_time =jisuan_date_time + String(jisuan_y)
IF jisuan_m < 10 THEN
jisuan_date_time =jisuan_date_time + "-0" + String(jisuan_m)
ELSE
jisuan_date_time =jisuan_date_time + "-" + String(jisuan_m)
END IF
IF jisuan_d < 10 THEN
jisuan_date_time =jisuan_date_time + "-0" + String(jisuan_d)
ELSE
jisuan_date_time =jisuan_date_time + "-" + String(jisuan_d)
END IF
IF shi < 10 THEN
jisuan_date_time =jisuan_date_time + " 0" + String(shi)
ELSE
jisuan_date_time =jisuan_date_time + " " + String(shi)
END IF
IF fen < 10 THEN
jisuan_date_time =jisuan_date_time + ":0" + String(fen)
ELSE
jisuan_date_time =jisuan_date_time + ":" + String(fen)
END IF
END IF
RETURN jisuan_date_time //返回函數(shù)值,String型
3自定義函數(shù)的應(yīng)用
3.1使用該函數(shù)應(yīng)注意的問(wèn)題
從程序代碼可以看到,為最大限度滿足其通用性,一方面,該函數(shù)不論是對(duì)幾分鐘的短時(shí)間段,還是對(duì)幾年的長(zhǎng)歷時(shí),都能正確返回差值或均值。另一方面,在使用系統(tǒng)函數(shù)時(shí),盡量兼顧各類(lèi)程序語(yǔ)言。例如,PowerScript函數(shù)庫(kù)中的Ceiling(n)函數(shù)能夠返回大于數(shù)值型變量n的最小整數(shù),但在這里沒(méi)有使用,而是使用的取整函數(shù)Int(),并對(duì)超出Integer型范圍的數(shù)進(jìn)行了處理。在使用該函數(shù)時(shí),除考慮不同軟件開(kāi)發(fā)語(yǔ)言的差別外,還應(yīng)注意以下幾點(diǎn):一是該函數(shù)在計(jì)算均值時(shí)考慮了“四舍六入,逢五奇進(jìn)偶舍”的原則,如果在實(shí)際應(yīng)用中不需要這種處理,就直接應(yīng)用系統(tǒng)的“四舍五入”(Round)函數(shù)。二是由于該函數(shù)是通過(guò)參數(shù)控制返回2個(gè)可選擇而且是不同類(lèi)型的結(jié)果,因此,不論是差值還是均值都已經(jīng)定義為字符型,那么返回的數(shù)據(jù)在使用時(shí)都須進(jìn)行數(shù)據(jù)類(lèi)型轉(zhuǎn)換。三是該函數(shù)操作和返回的數(shù)據(jù)均精確到分鐘,如果實(shí)際需要更精確,可通過(guò)增加循環(huán)控制來(lái)實(shí)現(xiàn)。
3.2在實(shí)測(cè)流量、輸沙量管理系統(tǒng)中的應(yīng)用實(shí)例
該函數(shù)在筆者研制的實(shí)測(cè)流量、輸沙量管理系統(tǒng)中發(fā)揮了非常理想的作用,那就是在實(shí)測(cè)流量、輸沙量的計(jì)算過(guò)程中能獲取用戶輸入的起止2個(gè)施測(cè)時(shí)間,均為日期-時(shí)間型,由程序來(lái)取得平均施測(cè)時(shí)間以對(duì)應(yīng)本次瞬時(shí)流量和輸沙量,并據(jù)此點(diǎn)繪流量和輸沙量過(guò)程線,推算日平均流量和輸沙率,為了輔助報(bào)汛,還計(jì)算出累計(jì)過(guò)水量和輸沙總量。如表1。
表1 30909999_2007-12-28流量(輸沙)過(guò)程
本次過(guò)水總量為:864.2(104m3),輸沙總量為:146(t) |
施測(cè)(或內(nèi)插)時(shí)間 |
流量施
測(cè)號(hào)數(shù) |
水位
(m) |
流量
(Q) |
斷面平均
(含沙量) |
輸沙率
(Qs) |
歷時(shí)
(分鐘) |
日平均
流量 |
日平均
輸沙率 |
年 月 日 |
時(shí) 分 |
2007-12-28 |
00:00 |
|
|
0 |
0 |
0 |
0 |
20.4 |
0 |
2007-12-28 |
15:29 |
111 |
9.88 |
30.5 |
0 |
0 |
929 |
|
|
2007-12-29 |
00:00 |
|
|
29.2 |
0 |
0 |
511 |
28.3 |
0.145 |
2007-12-29 |
15:42 |
112 |
9.95 |
27.8 |
0 |
0 |
942 |
|
|
2007-12-30 |
00:00 |
|
|
28.0 |
0.030 |
0.840 |
498 |
28.2 |
1.27 |
2007-12-30 |
15:13 |
113 |
9.98 |
28.3 |
0.060 |
1.70 |
913 |
|
|
2007-12-31 |
00:00 |
|
|
28.3 |
0.030 |
0.849 |
527 |
23.1 |
0.268 |
2007-12-31 |
15:10 |
114 |
9.98 |
28.3 |
0 |
0 |
910 |
|
|
2008-1-1 |
00:00 |
|
|
0 |
0 |
0 |
530 |
|
|
實(shí)測(cè)流量、輸沙量成果表同過(guò)程線圖建立鏈接后,系統(tǒng)自動(dòng)插入各日00:00時(shí)和24:00時(shí)的數(shù)據(jù),按照連實(shí)測(cè)流量過(guò)程線法推流,可使用該自定義函數(shù)在任意兩個(gè)時(shí)間段內(nèi)插入一個(gè)均值時(shí)間及相應(yīng)的流量、輸沙量,再按照人為需要和過(guò)程線趨勢(shì)進(jìn)行手工調(diào)整,直到取得滿意的過(guò)程線后實(shí)施相應(yīng)的計(jì)算功能。該函數(shù)在計(jì)算各時(shí)段的歷時(shí)過(guò)程中,為該程序模塊取得了事半功倍的效果。
4結(jié)語(yǔ)
本文給出的這一函數(shù),從思路到實(shí)現(xiàn)的過(guò)程都是嚴(yán)密的,全面考慮了各種情況,大量的實(shí)際應(yīng)用更表明了該函數(shù)具有簡(jiǎn)單性、通用性、易操作性和可靠性,而且作為自定義函數(shù),調(diào)入計(jì)算機(jī)內(nèi)存后同系統(tǒng)函數(shù)的運(yùn)算效果是相同的,在此提供給廣大同仁及愛(ài)好者。當(dāng)然,這只是筆者在水文資料電算中的一點(diǎn)經(jīng)驗(yàn)之談,不妥之處,敬請(qǐng)指正。