[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
回复 48# plp626

这里不考虑 terse 提出的历法变化问题,

42 楼给出的测试方式是 假定一个 简单易懂易实现的 日期生成 算法 是正确的, 用它从 某个日期 开始依次生成某范围内所有后续的日期.
这样生成的一个日期序列的序号对应着整数序列的一部分,

index = date2index(测试起始日期)
loop (简单算法生成 y.m.d,  直到测试终止日期, (y.m.d)++) {
  y.m.d   ->  i = date2index(y.m.d)   ->   yy.mm.dd = index2date(i)
  上过程中: (i ≠ index)  或者 (yy.mm.dd ≠ y.m.d) 即发现错误
  index++
}

bat 测试确实很慢, 还好没事开着不管它, 写成高级语言的也容易, 下面是已经完成测试过的 bat:
  1. @echo off & setlocal enabledelayedexpansion
  2. REM Index := date2index(1.1.1);
  3. set /a "y=1,m=1,d=1"
  4. set /a "m+=9, m%%=12,y-=m/10, i=365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + d - 1"
  5. set /a "Index=i"
  6. for /l %%y in (1 1 20000) do (
  7.   set "y=%%y"
  8.   set /a "leap = (^!(%%y %% 4) & ^!^!(%%y %% 100)) | ^!(%%y %% 400)"
  9.   if "!leap!"=="1" (set "eFeb=29") else set "eFeb=28"
  10.   for %%t in ("1 31" "2 !eFeb!" "3 31" "4 30" "5 31" "6 30" "7 31" "8 31" "9 30" "10 31" "11 30" "12 31") do (
  11.     for /f "tokens=1,2" %%m in ("%%~t") do (
  12.       set "m=%%m"
  13.       for /l %%d in (1 1 %%n) do (
  14.         set "d=%%d"
  15.         REM testing...
  16.         REM if date2index(y.m.d) <> Index (
  17.           REM error
  18.         REM )
  19.         REM if index2date(date2index(y.m.d)) <> y.m.d (
  20.           REM error
  21.         REM )
  22.         REM Index += 1;
  23.         set /a "m+=9, m%%=12,y-=m/10, i=365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + d - 1"
  24.         if "!i!" neq "!Index!" ((echo error at %%y.%%m.%%d date2index(y.m.d^)=!i!^<^> !Index!) & pause)
  25.         set /a "y=(i*99+145)/36159,y+=i-365*y-y/4+y/100-y/400>>31,d=i-365*y-y/4+y/100-y/400,m=(5*d+2)/153,d+=1-(153*m+2)/5,y+=m/10,m=(m+2)%%12+1"
  26.         set /a "error=(y-%%y)|(m-%%m)|(d-%%d)"
  27.         if "!error!" neq "0" ((echo error at %%y.%%m.%%d index2date(date2index(y.m.d^)^)=!y!.!m!.!d!) & pause)
  28.         echo %%y.%%m.%%d  Index=!Index!
  29.         set /a "Index+=1"
  30.       )
  31.     )
  32.   )
  33. )
  34. pause
  35. exit
复制代码

TOP

本帖最后由 neorobin 于 2012-4-11 23:02 编辑

回复 49# plp626

31 楼, 我做了年份估值误差范围测试, 如果估值函数在给定计算范围内的 估值误差范围 跨过 两个整数(比如 [-0.1,1.3] 跨过了 0 和 1 两个整数), 就不利于后续代码, 后面年份的误差调整就不是简单的只作出 要么不变, 要么加1(或者减1) 这样的方式了, 因为 跨过两个整数 意味着误差的整数绝对值跨度将达到 2.

TOP

本帖最后由 neorobin 于 2012-4-11 23:10 编辑

回复 53# plp626


    用个能算到 公元 3000 年的历法就蛮足够了, 往过去可以算 100 年也就可以了, 我们不考古, 呵呵,  我用过最大的用途就是看下出生日期什么的.


51 楼纠正一下, 应说成 整数误差绝对值 跨度 将达到 2: 例如, 应该得到的 年份是 2012, 但误差范围可能出现 3 种(据算法择其中一种)可能的区间 [2010,2012], [2011,2013], [2012,2014], 尽管这个误差正峰值和负峰值并不会发生在对同一个年份的估值上, 但代码上总是要对这两个峰值作统一处理的.

TOP

本帖最后由 neorobin 于 2012-4-11 23:32 编辑

回复 57# plp626


    我测试的结果是 [1,3000] 内,  (i * 4 + 93) / 1461 就可行

(i * 4 + 0) / 1461
The pOffsMin is: -0.062971;  the pOffsMax is: 0.000000
The pMin is: 3000;  the pMax is: 4
pOffsMin = -0.062971,  pOffsMax + 365*4 / 1461 = 0.999316

0.062971 * 1461 = 92.000631

(i * 4 + 93) / 1461
The pOffsMin is: 0.000000;  the pOffsMax is: 0.063655
The pMin is: 4;  the pMax is: 4
pOffsMin = 0.000000,  pOffsMax + 365*4 / 1461 = 1.062971

TOP

回复 59# plp626

测试代码确实有问题, 是记录 误差最小值的一个变量的初始值设小了,  但 93 这个常数还是碰对了

修改后:
   
93
The pOffsMin is: 0.000684;  the pOffsMax is: 0.063655
The pMin is: 3000;  the pMax is: 4
pOffsMin = 0.000684,  pOffsMax + 365*4 / 1461 = 1.062971



0
The pOffsMin is: -0.062971;  the pOffsMax is: 0.000000
The pMin is: 3000;  the pMax is: 4
pOffsMin = -0.062971,  pOffsMax + 365*4 / 1461 = 0.999316

0.062971 * 1461 = 92.000631

第一次出错的发生:
3002.2.28  Index=1096456
error at 3002.3.1 index2date(date2index(y.m.d))=3002.2.29

TOP

回复 64# plp626

如果只是以 由序号得到的日期是否合法来测试 index2date, 我认为是不妥的:

比如: 由 i 得到了 2012.4.10, 而接着 i+1 得到的却是 2011.4.11, ??? 日期都是合法的, 但序列乱了, 也许可以证明出现 序列乱了 也必然出现非法日期, 但至少现在没有证明这一点

TOP

回复 66# plp626


{1,2,3} <--> {2012.4.12, 2012.4.16, 2012.4.30}

形如上面的互逆映射关系, 也许这里我们讨论的算法不会形成, 但如果某算法造成这样的关系, 那么不能保证日期的连续增 1 的检测方式是检测不出那种算法的错误的.

TOP

返回列表