【问题标题】:gforth get dayname from a user specified dategforth 从用户指定的日期获取日期名称
【发布时间】:2021-06-08 07:46:56
【问题描述】:

我尝试应用 zeller 收敛简化方法从用户输入的日期中获取日期名称。

来自

的简化算法
\ Zeller's Congruence
variable year       2   allot
variable day        2   allot
variable mounth     2   allot
variable century    2   allot
variable daynumber  1   allot
variable k          2   allot
variable j          2   allot

\ read keyboard word input
: input$ ( n -- addr n )
        pad swap accept
        pad swap
;

\ check input type
: input# ( -- u true | false )
        0. 16 input$ dup >R
        >number nip nip
        R> <> dup 0 = if
                nip
        then
;

\ get all year mounth and day to check
: readyear
        CR ." Year    ? "
        input# if
                year !
        else
                cr ." Must be a number" cr
                bye
        then
        year @ dup >r 99 > r> 1 < or if \ more forth way to write it
                cr ."  Must be lower than 99 and gregorian date ( so also over 1752 September 2cd)" cr
                bye
        then
;

: readday
        CR ." Day     ? "
        input# if
                day !
        else
                cr ." Must be a number" cr
                bye
        then
        day @ dup >r 31 > r> 1 < or if
                cr ."  Must be between 1 and 31" cr ( is user stupid ? )
                bye
        then
;

: ?adaptday
                \ NOTE: In this algorithm January and February are
                \      counted as months 13 and 14 of the previous
                \      year.E.g. if it is 2 February 2010, the
                \      algorithm counts the date as the second day
                \      of the fourteenth month of 2009 (02/14/2009
                \      in DD/MM/YYYY format)
        mounth @ case
            1 of
                mounth 13 !
                year @ 1- !
            endof
            2 of
                mounth 14 !
                year @ 1- !
            endof
        endcase
        \                      13(m+1)          K       J
        \ daynumber = ( day + (-------) + k + (---) + (---) + 5j ) %7
        \                         5             4       4
        year 100 mod k !
        year 100 / j !
        day @ mounth @ 1 + 13 * 5 / +       \ day + ((13*(m-1))/5)
        k @ +                               \ day + ((13*(m-1))/5) + k
        k @ 4 / +                           \ day + ((13*(m-1))/5) + k + k/4
        J @ 4 / +                           \ day + ((13*(m-1))/5) + k + k/4 + J/4
        J @ 5 * +                           \ day + ((13*(m-1))/5) + k + k/4 + J/4 + 5J
        7 mod daynumber !                   \ (day + ((13*(m-1))/5) + k + k/4 + J/4 + 5J) %7
        \ 1 line for each sub calculation just for better mathematical reading
        daynumber @ case
            0 of cr ."      Saturday       !" cr bye endof
            1 of cr ."      Sunday         !" cr bye endof
            2 of cr ."      Monday         !" cr bye endof
            3 of cr ."      Tuesday        !" cr bye endof
            4 of cr ."      Wednesday      !" cr bye endof
            5 of cr ."      Thursday       !" cr bye endof
            6 of cr ."      Friday         !" cr bye endof
        endcase
;

\ main function
: main
        page
        cr
        >readvars
        ?adaptday
        cr cr
        bye
;

main

语法似乎没问题,但方法或错误/失败的功能可能是根本原因。

输入很好,但随机获得的日期不是好的一天(即使是同一天)

所以我可能没有做某事&在这里我未优化代码以尝试调试它,但我还没有找到原因。

这是一个执行示例:

插入日期:

????francois@????zaphod????:~/GITLAB/dev/dev_gforth_calendar$ gforth zellersconvergence_bugged.fs
redefined k  redefined j


Insert a decomposed date :

Century ? 20
Year    ? 21
Mounth  ? 6
Day     ? 8

     Tuesday        !
????francois@????zaphod????:~/GITLAB/dev/dev_gforth_calendar$ gforth zellersconvergence_bugged.fs
redefined k  redefined j


Insert a decomposed date :

Century ? 20
Year    ? 21
Mounth  ? 6
Day     ? 8

     Saturday       !
????francois@????zaphod????:~/GITLAB/dev/dev_gforth_calendar$ gforth zellersconvergence_bugged.fs
redefined k  redefined j


Insert a decomposed date :

Century ? 20
Year    ? 21
Mounth  ? 6
Day     ? 8

     Monday         !
????francois@????zaphod????:~/GITLAB/dev/dev_gforth_calendar$

可能是堆栈问题? 可能是方法问题? 那么算法本身可能是一个被误解的东西?

谢谢

【问题讨论】:

  • 最好不要从单词中执行bye。这样您就有机会检查变量并在终端会话中重新运行代码。最初的问题是对变量的地址而不是它们的内容求和。 @s 不见了。因此,当程序重新加载时,它们可能位于不同的地址,因此会给您不同的答案。
  • 哦,你说得对,例如,我错过了year @,再见,我将标记退出状态,谢谢。

标签: calendar calculation date-arithmetic forth gforth


【解决方案1】:

您需要从年份变量year @ 100 ... 中获取数据两次。我认为在那之后?adaptday 会起作用。还有第四个词within \ n lo hi -- flag ; flag is True if lo &lt;= n &lt; hi 用于检查范围内的数字,

在 Forth 中使用这么多变量是不寻常的。这些值通常存储在堆栈中。 j 作为变量可以覆盖用作外部循环计数器的 j。我也看到 k 用于下一个外循环!

我会像这样实现它。然后我可以使用堆栈输入在控制台中运行这些单词,以查看发生了什么以帮助调试。

: century-ix  \ c -- days-ix
  dup 4/ swap 5 * + 
;
: year-ix   \ yy -- days-ix
  dup 4/ +  
;
: month-ix  \ mm - days-ix
  1+ 13 * 5 / 
;
: weekday \ dd mm yyyy -- dow
  over 3 < if
    swap 12 + swap 1-  \ adjusts Jan and Feb to be month 13 or 14 of previous year.
  then 
  100 /mod  ( dd mm yy cc )
  century-ix            ( dd mm yy days )
  swap year-ix +        ( dd mm days )
  swap month-ix + +     \ Calculate for months and days
  7 mod 
; 

: weekday.  \ n -- ;  -- Prints weekday in English
            \  Too useful to hide in another definition.
  case
        0 of cr ."      Saturday       !" cr  endof
        1 of cr ."      Sunday         !" cr  endof
        2 of cr ."      Monday         !" cr  endof
        3 of cr ."      Tuesday        !" cr  endof
        4 of cr ."      Wednesday      !" cr  endof
        5 of cr ."      Thursday       !" cr  endof
        6 of cr ."      Friday         !" cr  endof
  endcase
; 

8 6 2021 weekday weekday. 
     Tuesday        !

【讨论】:

    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2012-01-12
    • 2015-10-21
    • 2017-04-17
    • 1970-01-01
    相关资源
    最近更新 更多