使用列表推导式对非负数的数字求和

问题描述

我正在寻找像这样的非负数的数字总和(“交叉总和”)的非递归实现:

cs :: Int -> Int 
cs n = sum digits_of_n where digits_of_n = [ . | ... ] 

一个数字的交叉和(例如 512)是其各个数字的总和(例如 5 + 1 + 2 = 8)

cs 接受一个非负数“n”作为输入,然后应该使用列表推导将数字拆分为其数字(例如 1234 -> [1,2,3,4]),然后将其相加。

使用列表理解的部分是问题,我不知道如何实现。

“通常”的递归方法是使用模和除法递归地从数字中提取数字,然后像这样总结它们:

cs :: Int -> Int
cs n = if n == 0 then 0 else n `mod` 10 + cs (n `div` 10)

然而,我很难在没有递归和列表理解的情况下表达这一点,有人对此有什么想法吗?

解决方法

首先让我指出,这样的数字总和几乎完全没有用处,而且这里有太多关于它们的问题。

...无论如何 - 您的问题归结为编写一个函数 Int -> [Int] 来生成非负数的数字列表。嗯,这当然可以递归完成,它可以使用 show 完成(这有点黑客,但是,任何需要十进制数字的东西 em> 将是一个 hack),带有 unfold,或者确实带有列表理解。在这种情况下,您不能再终止使用所有数字,但您仍然可以先计算数字的数量,然后确定每个 i 数字分别:

decimalDigits :: Int -> [Int]
decimalDigits n = [ _ | i <- [0 .. ceiling . logBase 10 $ fromIntegral n ]

然后,要计算第 i 位数字,您需要像在递归解决方案中一样使用 moddiv,只是不是使用 10,而是使用它的 { {1}} 次幂。

,

这是一种可能的方法:

f x = [(x `mod` (10 ^ y)) `div` (10 ^ (y-1)) | y <- [1.. ceiling $ logBase 10 $ fromIntegral x]]

这里假设输入的数字是整数。它首先计算大于输入的以 10 为底的对数最接近的整数。该值为下一步提供了一个边界,我们使用 divmod 的组合将数字拆分为数字。把所有东西放在一起,我们最终得到了从右到左的数字。

,

另一个间接

sumdigits = sum . map digitToInt . show

你需要import Data.Char(digitToInt)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...