我目前正在尝试使用Ocaml中没有库函数的大整数实现乘法。
这是我到目前为止所做的:
let rec mulByDigit i l =
match l with
[] -> []
| h::t ->
match t with
[] -> [(h*i) mod 10]
| x::y ->
match y with
[] -> [x*i/10+(h*i) mod 10]@mulByDigit i t
| a::b -> [(x*i/10+(h*i)mod 10+(a*i/10+(x*i)
mod 10)/10) mod 10]@mulByDigit i t
对于i = 9和l = [9; 9; 9; 9]给出了[9; 9; 9; 1]当需要的是[8; 9; 9; 9; 1]
据我了解,其算法是从最后一位* i,当前数字* i和下一位* i获取信息,以构建答案列表的当前数字。然而,有两种情况并非如此。对于答案列表的第一个数字和最后一个数字,最后一个数字取自输入列表的当前数字* i和前一个数字* i的信息,第一个数字取自当前数字* i和后续数字的信息*我的输入列表。我可以处理最后一个数字的特殊情况,因为最后一个数字与[]的匹配,但我无法弄清楚如何为第一个数字做特殊情况,因为我没有看到任何条件我可以放入if then语句仅在此函数的初始调用时发生。
任何帮助都将不胜感激。
答案 0 :(得分:3)
嗯,这听起来有点像家庭作业问题。以下是一些观察结果。
如果您使用列表顶部的单位数字而不是尾部表示您的数字,您可能会看到更漂亮的代码。您通常希望处理从单位结束开始的事情,并且它具有数学上的正确性(列表中第n个位置的乘数为10 ** n)。但也许你无法掌控自己的代表性。
在一般情况下,你有一个随身携带。如果你认为你的内部函数有三个输入(大数字的下一个数字,整数乘以,携带)你可能会使事情有效。
你绝对不想在第一次调用它们时考虑做出不同的功能!这不是一个功能,这是必要的编程。
此致
答案 1 :(得分:1)
我会考虑以不同的方式打破这种情况。例如,你可以编写一个函数,它只是乘法而不用担心携带,然后是第二个处理携带的函数。
正如杰弗里建议的那样,你也可以通常或者根据需要反转数字。虽然您可能不允许使用List.reverse函数,但您可以在大约一行代码中自行实现。
哦,为了提高效率和/或良好的习惯,你应该重写那些说[one value]@list
代替(one value)::list
的部分。他们会做同样的事情,第二个会比第一个更快(除非编译器足够聪明,可以为你做这个替换,它可能是,在这种情况下,它将是相同的速度)。