0

如果传递的参数是合理的日期,我有以下函数应该返回 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
4

3 回答 3

2

您当前的解决方案是不可能维护的,它的逻辑看起来像是下地狱再回来的东西:)

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

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)

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

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))
于 2013-01-23T18:33:43.363 回答
1

您反复使用诸如if #2 x = 1 mod 2. 这几乎肯定不会像您想象的那样起作用。这里,mod是一个算术运算符,表示将 1 除以 2 时获得的余数,而不是说#2 x等于 1 模 2 的数学表达式。因此,不是测试是否#2 x是奇数,而是测试它是否等于 1。通过你的条件,你真的只允许truewhen#2 x是 1,所以你的合理日期必须都在 1 月(甚至可能没有,我还没有完成所有条件)。

于 2013-01-23T16:22:13.763 回答
-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)

于 2013-01-24T08:26:31.723 回答