为IF编写可变数量的参数 [英] Write a variable number of arguments for IF
问题描述
我正在尝试编写一个可以解决此问题的任何常规版本的函数:
I am trying to write a function that would solve any general version of this problem:
如果我们列出所有低于10的自然数,它们是3或5的倍数,则得到3、5、6和9.这些倍数的总和为23.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
找到1000以下的3或5的所有倍数之和.
Find the sum of all the multiples of 3 or 5 below 1000.
我为此实例解决的方法是:
The way I solved it for this instance was:
multiples = Array(Int, 0)
[ (i % 3 == 0 || i % 5 == 0) && push!(multiples, i) for i in 1:1000 ]
sum(multiples)
我想编写一个函数,该函数将使用多个数组(在本例中为[3,5])和最终数字(在本例中为1000).关键是数组可以由任意多个数字组成,而不仅仅是两个数字(例如[3,5,6]).然后,该函数应为每个N
运行i % N == 0
.
I want to write a function that will take an array of multiples (in this case, [3,5]) and the final number (in this case, 1000). The point is that the array can consist of arbitrarily many numbers, not just two (e.g., [3,5,6]). Then the function should run i % N == 0
for each N
.
我如何最有效地做到这一点?可能涉及元编程吗? (代码不必采用列表理解格式.)
How do I do that most efficiently? Could that involve metaprogramming? (The code doesn't have to be in a list comprehension format.)
谢谢!
推荐答案
使用模除法和函数式样式,出现在我头上的第一件事是
Very first thing that popped into my head was the following, using modulo division and a functional style:
v1(N,M) = sum(filter(k->any(j->k%j==0,M), 1:N))
但是我想研究一些替代方法,因为这有两个问题:
But I wanted to investigate some alternatives, as this has two problems:
- 两个级别的匿名功能,Julia尚未很好地进行优化(到目前为止).
- 根据范围创建一个临时数组,然后求和.
因此,这是最明显的替代方案,即单衬套的 C样式版本:
So here is the most obvious alternative, the C-style version of the one-liner:
function v2(N,M)
sum_so_far = 0
for k in 1:N
for j in M
if k%j==0
sum_so_far += k
break
end
end
end
return sum_so_far
end
但是后来我再考虑了一下,记得在某处读到模除法是一个缓慢的操作.我想看看IntSet
的表现-专门用于整数的集合.所以这是另一种单行代码, IntSet
,不使用任何模块划分,以及一种功能样式!
But then I thought about it some more, and remembered reading somewhere that modulo division is a slow operation. I wanted to see how IntSet
s perform - a set specialized for integers. So here is another one-liner, IntSet
s without using any module division, and a functional style!
v3(N,M) = sum(union(map(j->IntSet(j:j:N), M)...))
将地图扩展到for
循环中,并将union!
重复应用于单个IntSet
并没有太大的好处,因此在此不再赘述.要对此进行细分:
Expanding the map into a for
loop and repeatedly applying union!
to a single IntSet
was not much better, so I won't include that here. To break this down:
-
IntSet(j:j:N)
是j和N之间j的所有倍数. -
j->IntSet(j:j:N)
是一个匿名函数,返回该IntSet
-
map(j->IntSet(j:j:N), M)
将该函数应用于M中的每个j,并返回Vector{IntSet}
. -
...
将向量喷溅"到union
的参数中
-
union
创建一个IntSet
作为其参数的并集-在这种情况下,为M中所有数字的倍数 - 然后我们总结一下
IntSet(j:j:N)
is all the multiples of j between j and Nj->IntSet(j:j:N)
is an anonymous function that returns thatIntSet
map(j->IntSet(j:j:N), M)
applies that function to each j in M, and returns aVector{IntSet}
.- The
...
"splats" the vector out into arguments ofunion
union
creates anIntSet
that is the union of its arguments - in this case, all multiples of the numbers in M- Then we sum it to finish
我对这些进行了基准测试
I benchmarked these with
N,M = 10000000, [3,4,5]
为您提供
- 单线:
2.857292874 seconds (826006352 bytes allocated, 10.49% gc time)
- C风格:
0.190581908 seconds (176 bytes allocated)
- IntSet无模数:
0.121820101 seconds (16781040 bytes allocated)
- One-liner:
2.857292874 seconds (826006352 bytes allocated, 10.49% gc time)
- C-style:
0.190581908 seconds (176 bytes allocated)
- IntSet no modulo:
0.121820101 seconds (16781040 bytes allocated)
因此,您绝对可以甚至用更高级别的对象来击败C风格的代码-模是昂贵的!关于无模数的整洁之处在于它很容易并行化:
So you can definitely even beat C-style code with higher level objects - modulo is that expensive I guess! The neat thing about the no modulo one is it parallelizes quite easily:
addprocs(3)
@everywhere worker(j,N) = IntSet(j:j:N)
v4(N,M) = sum(union(pmap(j->worker(j,N),M)...))
@show v4(1000, [3,5])
@time v3(1000000000,[3,4,5]); # bigger N than before
@time v4(1000000000,[3,4,5]);
给出
elapsed time: 12.279323079 seconds (2147831540 bytes allocated, 0.94% gc time)
elapsed time: 10.322364457 seconds (1019935752 bytes allocated, 0.71% gc time)
这不是好多了,但是我想是这样的.
which isn't much better, but its something I suppose.
这篇关于为IF编写可变数量的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!