我看到了关于 cast+exceptions 与正则表达式的未解决讨论,我想我会尝试对所有内容进行基准测试并得出一个客观的答案:
以下是此处尝试的每种方法的最佳情况和最差情况的来源:
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 秒。如果我们将其除以最坏情况下的时间量,我们可以估计需要多少次运行才能达到收支平衡,但例外情况会减慢投射速度以匹配正则表达式速度。 0.3 的大约 6 秒为我们提供了大约 20 秒。因此,如果性能很重要,并且您预计不到 20 分之一的测试失败,那么使用 cast+exceptions。
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 次导致异常。
因此,只有在发生真正异常的事情时才应使用异常,这是您和您的代码库的决定。当它们不被使用时,它们所在的代码可以更简单、更快。
如果性能无关紧要,您可能应该只遵循您的团队或代码库已有的任何约定,而忽略整个答案。