我想知道为什么我的代码不起作用。我是代码世界的新手,所以如果有人能为我解决这个问题,那么最好如何解决它,谢谢!
我正在尝试创建一个程序,它将从我指定的数字列表中指示素数。
请告诉我为什么这两个代码不起作用!我很困惑第二个代码试图做什么,因为我发现它是别人对我的问题的解决方案。我是编码的新手,但我喜欢它,所以忍受我!
这是我的简单代码:
def is_prime?(*nums)
i = 2
nums.each do |num|
while i < num
if num % i == 0
puts "#{num} is not a prime"
else
puts "#{num} is a prime"
end
i += 1
end
end
end
....为什么这不起作用?我怎样才能让它发挥作用?它一直给我一个奇怪的答案,因为它卡在我的第一个数字上并且似乎没有处理我插入的下一个数字:
puts is_prime?(21, 23, 17)
这是我无法正确运行的第二个代码。有人可以打破这里发生的事情吗?我怎样才能让它发挥作用?
def is_prime?(*nums)
nums.each_with_object({}) do |num, hsh|
hsh[num] = num > 1 && 2.upto(num - 1).none? {|i| num % i == 0}
end
end
puts is_prime?(27, 13, 42)
无论如何,我知道这个问题有点令人困惑,但如果有人关心输入他们的2美分我会很感激!哦,最后我如何正确地在问题板上发布代码?没有导师,我是如此新奇,如此迷茫!
答案 0 :(得分:10)
素数排除了均衡(当然除了2),因此您可以在外部和内部循环中跳过它们。一旦你发现数字是素数,打破循环。其中两种技术可以大大加快算法速度,我的实验是在10000阵列上从3.9秒下降0.2秒。
标准的inneficient算法首先:
class PrimeNumbers
def initialize(size)
@array = (2..size).to_a
@prime = []
raise ArgumentError if size < 2
end
def process
@array.each do |i|
@prime.push(i) if inner_loop(i)
end
@prime
end
private
def inner_loop(e)
is_prime = true
e.downto(2) do |k|
next if k == e
if e % k == 0
is_prime = false
break
end
end
is_prime
end
end
下一步是问这些问题:
所以让我们看看算法速度快30倍(输入50000大小,与第一个算法版本相比需要3秒而不是98秒):
class PrimeNumbers
def initialize(size)
raise ArgumentError if size < 2
@array = 1.step(size,2).to_a
@array.shift
@prime = [2]
end
def process
@array.each do |i|
@prime.push(i) if inner_loop(i)
end
@prime
end
private
def inner_loop(e, is_prime = true)
3.step(e/3, 2) do |k|
if e % k == 0
is_prime = false
break
end
end
is_prime
end
end
取决于算法效率时间结果可以如下(原始数组50000大小):
96.824695s (loop through all array)
92.385227s (loop through all array, skip even numbers in inner loop)
9.251714s (loop through all array, skip even numbers in outer loop)
5.901579s (loop through outer loop odds only)
3.480197s (loop through outer loop odds only, cut half)
2.329469s (loop through outer loop odds only, cut two thirds)
为什么减少一半?因为67/51不能是Integer。为什么要削减第三?有很强的依赖性。查看奇数的分隔符:
<强>更新强>:
深入研究算法我发现不需要循环初始数组的一半甚至三等大小。最后,您可以迭代不到10%的数组来拒绝复合数字。
相对容易切割1/2或1/3,但要削减4/5你必须排除9,切割7/8 - 9,15,25等。它有助于循环只有小集忽略数组其余部分的数据。请参阅下图中的更多详细信息:
0.398072s (loop through odds only, cut selective block depend on initial size)
选择性阻止是什么?让我们选择数组大小,例如8000并查看变量:
size = 8000
@loop_end = 19
@denominators = [9, 15, 21, 27, 33, 39, 45, 51, 25, 35, 45, 55, 65, 75, 85, 49, 63, 77, 91, 105, 119, 81, 99, 117, 135, 153, 121, 143, 165, 187, 169, 195, 221, 225, 255, 289]
您需要循环的最大值数为5%(19/20)!因此,要比较给定值,不需要循环超过前5-10%的值。
对于算法,循环通过421个元素以选择素数就足够了。如果输入更大,@ toop_end将适应。在较小的数据集(1000个值)上,变量是:
size = 1000
@loop_end = 9
@denominators = [9, 15, 21, 25, 35, 49]
循环遍历111个元素有助于找出1000个元素数组中的素数。尽管@denominators数组大于实际分母(参见上面的电子表格),但它不会影响算法的正确性。我们拒绝@denominators并使用第2步循环到元素/ @ loop_end 以避免偶数。
对320x速度算法进行优化是非常令人印象深刻的。请参阅下面的代码:
class PrimeNumbers
def initialize(size)
raise ArgumentError if size < 2
prepare_vars(size)
end
def process
@array.each do |i|
next if @denominators.include?(i)
@prime.push(i) if test_of_prime(i)
end
@prime
end
private
def prepare_vars(size)
@prime = [2]
@array = 1.step(size,2).to_a
@array.shift
@loop_end = (size**(1/3.0)).to_i
@loop_end += 1 if (@loop_end % 2 == 0)
@denominators = []
3.step(@loop_end-2,2).each do |i|
i.step(@loop_end-2,2).each do |k|
@denominators << i * k
end
end
end
def test_of_prime(e, is_prime = true)
3.step(e/@loop_end, 2) do |k|
if e % k == 0
is_prime = false
break
end
end
is_prime
end
end
单元测试可在下面找到:
require 'minitest/autorun'
class PrimeNumbersTest < Minitest::Unit::TestCase
def test_valid_1
assert_equal [2], PrimeNumbers.new(2).process
end
def test_valid_2
assert_equal [2, 3, 5, 7, 11], PrimeNumbers.new(11).process
end
def test_valid_3
assert_equal [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47], PrimeNumbers.new(50).process
end
def test_valid_4
assert_equal [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97], PrimeNumbers.new(100).process
end
def test_valid_5
assert_equal [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797], PrimeNumbers.new(800).process
end
def test_valid_6
assert_equal [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499], PrimeNumbers.new(1500).process
end
def test_valid_7
assert_equal [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993], PrimeNumbers.new(8000).process
end
def test_invalid_8
assert_raises( ArgumentError ) { PrimeNumbers.new(1) }
end
end
<强> UPDATE2 强>
Sierat of Eratosthenes算法更快。
答案 1 :(得分:3)
你有一些问题。之前确定了一个:声明i = 2
的位置。这是修复后的代码。
def is_prime?(*nums)
nums.each do |num|
i = 2
while i < num
if num % i == 0
puts "#{num} is not a prime"
else
puts "#{num} is a prime"
end
i += 1
end
end
end
当您num % i == 0
确定该号码不是素数时,并打印出相应的消息,然后您继续检查它是否可以整除所有大于num
的数字。每次num % i == 0
您打印出它不是素数。关键是,一旦确定数字不是素数,就不需要继续检查。
另一个问题是,无论何时打印num % i != 0
,该数字都是素数。然而,那是不成熟的。在确定num % i != 0
所有小于num
的整数之前,您无法得出该结论。
让我们看看如何解决这些问题。我认为最简单的方法是编写一个单独的方法来确定单个数字是否为素数。我已将该方法称为is_prime?
并重命名为主要方法is_each_prime?
。
def is_each_prime?(*nums)
nums.each { |num|
puts "#{num} is #{ is_prime?(num) ? '' : "not " }a prime" }
end
def is_prime?(num)
(2...Math.sqrt(num)).all? { |i| num % i != 0 }
end
puts is_each_prime?(21, 23, 17)
#=> 21 is not a prime
# 23 is a prime
# 17 is a prime
创建单独方法is_prime?
的一个好处是,您可以单独测试它,以确保它正常工作。
答案 2 :(得分:0)
您在循环外部初始化了i
,因此后续数字首先通过已设置为某个高值的i
进行测试。