繁体   English   中英

Haskell整数奇数位检查器

[英]Haskell Integer Odd Digits Checker

我似乎陷入了一个问题,不知道如何处理它或我当前的代码做错了什么。

我必须编写一个名为oddDigits的函数,它接受一个整数参数并返回一个布尔结果。 当且仅当参数是具有奇数位数的正整数时,它应该返回True。 如果参数为零或负数,则函数应该以错误消息停止。

此外,无法将参数转换为字符串。 必须使用递归。 我感觉每个数字可以递归地存储在列表中,然后列表的长度可以确定答案。

到目前为止,我有这个:

oddDigits :: Integer -> Bool 

lst = [] 

oddDigits x 
    | (x < 0) || (x == 0) = error 
    | x `mod` 10 ++ lst ++ oddDigits(x `div` 10) 
    | length(lst) `mod` 2 /= 0 = True
    | otherwise = False 

对不起,如果代码看起来很糟糕。 我是Haskell的新手,还在学习。 我究竟做错了什么,我怎么能纠正它?

首先,这看起来很奇怪。 或许你做错了就是要考虑这个问题......

XKCD维基百科打印机

但是如果你坚持下去,你想知道一个奇数位数的整数的属性......哦。 有很多可以改进的地方。 首先, (x < 0) || (x == 0) (x < 0) || (x == 0)不需要括号 - <== (中缀4)绑定比||更紧密 如果您对此不确定,可以随时询问GHCi:

Prelude> :i ==
class Eq a where
  (==) :: a -> a -> Bool
  ...
    -- Defined in ‘GHC.Classes’
infix 4 ==
Prelude> :i ||
(||) :: Bool -> Bool -> Bool    -- Defined in ‘GHC.Classes’
infixr 2 ||

但在这里你不需要|| 无论如何,因为有一个小于或等于的专用运算符。 因此你可以写

oddDigits x 
  | x <= 0  = error "bla bla"
  | ...

然后, 可以将数字“转换”为字符串。 转换为字符串通常是一个非常令人讨厌的事情,因为它会抛出窗口中的所有结构,类型检查等; 但“数字位数”基本上字符串的属性(十进制扩展),而不是数字本身,因此对于此特定任务而言,这并非完全不可见。 这可行:

oddDigits x 
 | x <= 0                      = error "blearg"
 | length (show x)`mod`2 /= 0  = True
 | otherwise                   = False 

然而,这是一个多余的冗余部门。 你正在检查某些东西是否为True ,然后给出True作为结果......为什么不把它放在一个子句中:

oddDigits x 
 | x <= 0     = error "blearg"
 | otherwise  = length (show x)`mod`2 /= 0

这可能实际上是最好的实现。

对于任何正确 ,明智的任务,我不建议去字符串路线。 递归更好。 这是它的样子:

oddDigits 1 = True
oddDigits x 
 | x <= 0     = error "blearg"
 | otherwise  = not . oddDigits $ x`div`10

您转换为数字列表,然后查找列表长度的一般方法没有任何问题。 真正出错的地方是试图把所有东西塞进一个功能。 正如您第一手发现的那样,它使调试变得非常困难。 功能编程最适合非常小的功能。

如果你将整数转换为数字列表的责任分开,使用像这个答案digs函数,你的算法的其余部分简化为:

oddDigits x | x <= 0 = error
oddDigits x = odd . length $ digs x

leftaroundabout的最终答案是非常好的,但它对2,3和23这样的数字失败了。这是一个修复。

oddDigits x 
  | x <= 0     = error "blearg"
  | x < 10     = True
  | otherwise  = not . oddDigits $ x`div`10

它比我最初的答案要优雅得多,如下。 我将它包括在内,介绍一个常见的功能范例,即问题的工人/包装转换。 这里的包装器提供了接口,并将工作传递给另一个函数。 请注意,否定性检查现在只需要进行一次。

oddDigits :: Integer -> Bool
oddDigits x
   | x <= 0 = False
   | otherwise = oddDigits' True x

oddDigits' :: Bool -> Integer -> Bool
oddDigits' t x
   | x < 10 = t
   | otherwise = oddDigits' (not t) $ x `div` 10

oddDigits'带有一个内部数据,最初的Bool。 我的第一个想法是让Bool成为一个数字累加器,计算数字位数。 在这种情况下,需要提供“unwrapper”,在这种情况下是标准的“奇数”功能:

oddDigits x
   | x <= 0 = False
   | otherwise = odd . oddDigits'' 1  $  x

其中oddDigits'' :: Integer -> Integer -> Integer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM