我看到投+异常VS正则表达式悬而未决的讨论,我想我会尽力基准一切,并产生一个客观的答案:
这里是最好的情况下,源和最差每种方法的这里尝试:
require "benchmark"
n = 500000
def is_float?(fl)
!!Float(fl) rescue false
end
def is_float_reg(fl)
fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/
end
class String
def to_float
Float self rescue (0.0/0.0)
end
end
Benchmark.bm(7) do |x|
x.report("Using cast best case") {
n.times do |i|
temp_fl = "#{i + 0.5}"
is_float?(temp_fl)
end
}
x.report("Using cast worst case") {
n.times do |i|
temp_fl = "asdf#{i + 0.5}"
is_float?(temp_fl)
end
}
x.report("Using cast2 best case") {
n.times do |i|
"#{i + 0.5}".to_float
end
}
x.report("Using cast2 worst case") {
n.times do |i|
"asdf#{i + 0.5}".to_float
end
}
x.report("Using regexp short") {
n.times do |i|
temp_fl = "#{i + 0.5}"
is_float_reg(temp_fl)
end
}
x.report("Using regexp long") {
n.times do |i|
temp_fl = "12340918234981234#{i + 0.5}"
is_float_reg(temp_fl)
end
}
x.report("Using regexp short fail") {
n.times do |i|
temp_fl = "asdf#{i + 0.5}"
is_float_reg(temp_fl)
end
}
x.report("Using regexp long fail") {
n.times do |i|
temp_fl = "12340918234981234#{i + 0.5}asdf"
is_float_reg(temp_fl)
end
}
end
结果如下用mri193:
user system total real
Using cast best case 0.608000 0.000000 0.608000 ( 0.615000)
Using cast worst case 5.647000 0.094000 5.741000 ( 5.745000)
Using cast2 best case 0.593000 0.000000 0.593000 ( 0.586000)
Using cast2 worst case 5.788000 0.047000 5.835000 ( 5.839000)
Using regexp short 0.951000 0.000000 0.951000 ( 0.952000)
Using regexp long 1.217000 0.000000 1.217000 ( 1.214000)
Using regexp short fail 1.201000 0.000000 1.201000 ( 1.202000)
Using regexp long fail 1.295000 0.000000 1.295000 ( 1.284000)
由于我们只处理线性时间算法,我认为我们使用经验测量来进行概括。很明显,正则表达式更加一致,并且只会根据传递的字符串的长度而有所波动。没有失败时演员阵容明显更快,失败时演出速度更慢。
如果我们比较成功的时间,我们可以看到演员最好的情况比正则表达式最好的情况快大约0.3秒。如果我们根据最坏情况下的时间量来划分这个值,我们可以估计有多少运行需要打破,即使有例外,也会减慢演员的速度以匹配正则表达式的速度。大约6秒钟后,.3降低了20。因此,如果性能很重要,并且您预计在20次测试中不到1次失败,则使用投射+异常。
的JRuby 1.7.4具有完全不同的结果:
user system total real
Using cast best case 2.575000 0.000000 2.575000 ( 2.575000)
Using cast worst case 53.260000 0.000000 53.260000 (53.260000)
Using cast2 best case 2.375000 0.000000 2.375000 ( 2.375000)
Using cast2 worst case 53.822000 0.000000 53.822000 (53.822000)
Using regexp short 2.637000 0.000000 2.637000 ( 2.637000)
Using regexp long 3.395000 0.000000 3.395000 ( 3.396000)
Using regexp short fail 3.072000 0.000000 3.072000 ( 3.073000)
Using regexp long fail 3.375000 0.000000 3.375000 ( 3.374000)
Cast是仅稍快在最好的情况下(约10%)。假设这种差异适合进行概括(我不认为它是这样),那么盈亏平衡点在200到250之间,只有1个引起异常。
因此,只有在真正异常的事情发生时才会使用异常,这是您和您的代码库的决定。当他们不使用代码时,他们可以更简单,更快速。
如果性能并不重要,您应该遵循您的团队或代码库已有的任何约定,并忽略这整个答案。
你不应该避免使用救援在它的修饰形式? – Benjamin 2017-08-16 19:44:43
很好的答案。作为一个小建议,我会避免使用双重否定,因为它建议[这里](http://www.rubydoc.info/github/bbatsov/rubocop/Rubocop/Cop/Style/DoubleNegation) – 2018-01-05 19:43:09