我的功能出了什么问题

时间:2013-01-23 15:54:20

标签: sml smlnj

我有以下函数,如果传递的参数是合理的日期则返回true,否则返回false。问题是它即使在明显合理的日期也会返回假,我无法弄清楚它有什么问题。眼睛更敏锐的人请帮忙。这是:

fun reasonable_date(x: int*int*int) =
    if #1 x > 0 andalso #2 x > 0 andalso #2 x <= 12 andalso #3 x > 0 andalso #3 x <= 31 
    then                                
    if #2 x = 1 mod 2 andalso #2 x < 8 andalso #3 x <= 31 then true
         else if #2 x = 0 mod 2 andalso #2 x >= 8 andalso #3 x <= 31 
         then true
     else if #2 x = 0 mod 2 andalso #2 x < 8
     then
         if #2 x = 2 andalso (#3 x = 28 orelse #3 x = 29) then true
         else if #2 x = 0 mod 2 andalso #3 x <= 30 then true
         else false
         else if #2 x = 1 mod 2 andalso #2 x > 8 andalso #3 x <=30 then true 
     else false
     else false

3 个答案:

答案 0 :(得分:2)

您当前的解决方案无法维护,其逻辑看起来像是地狱般的东西:)

我建议您将其分解为更小的逻辑部分,以确保简单的属性。因此,不是首先测试年,月和日是否大于或等于1,您可以将所有关于年,月和日的逻辑分组给自己

fun daysInMonth n =
    List.nth([31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], n-1)

fun reasonable_date (y, m, d) =
    (* Check year >= 1 *)
    y >= 1 andalso

    (* Check 1 <= month <= 12 *)
    (m >= 1 andalso m <= 12) andalso

    (* Check 1 <= day <= n, for n being the number of days in specified month *)
    (d >= 1 andalso d <= daysInMonth m)

显然这不会处理闰年,但是如果月份是2月,使用辅助函数实现也很简单。它可以这样做

fun reasonable_date (y, m, d) =
    (* Check year >= 1 *)
    y >= 1 andalso

    (* Check 1 <= month <= 12 *)
    (m >= 1 andalso m <= 12) andalso

    (* Check 1 <= day <= n, for n being the number of days in specified month *)
    (d >= 1 andalso
     (* If February, and leap year *)
     ((m = 2 andalso isLeapYear y andalso d <= 29)
      (* Any other month or non leap year *)
      orelse d <= daysInMonth m))

答案 1 :(得分:1)

您反复使用if #2 x = 1 mod 2等条件。这几乎肯定不会像你想象的那样奏效。这里,mod是算术运算符,表示将1除以2时得到的余数,而不是表示#2 x等于1模2的数学表达式。因此,不是测试是否#2 x很奇怪,你正在测试它是否等于1.按照你的条件,当true为1时你真的只允许#2 x,所以你的合理日期必须全部在1月(甚至可能没有是任何,我没有完成所有条件)。

答案 2 :(得分:-1)

我更喜欢这种看起来更具可读性的解决方案

fun reasonable_date (y, m, d) =
    let val daysInMonth =
           List.nth([31, if isLeapYear y then 29 else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], m-1)
    in
        (* Check year >= 1 *)
        y >= 1 andalso

        (* Check 1 <= month <= 12 *)
        (m >= 1 andalso m <= 12) andalso

        (* Check 1 <= day <= n, for n being the number of days in specified month *)
        (d >= 1 andalso d <= daysInMonth)
    end

但可能是我错过了一些技巧(我假设你已经写了一个辅助函数isLeapYear)