Я видел неразрешенную дискуссию о приведениях + исключения к регулярному выражению, и я подумал, что постараюсь все сравнить и дать объективный ответ:
Вот источник для лучшего и наихудшего из каждого метода, который здесь пытался:
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. Поэтому, если производительность имеет значение, и вы ожидаете, что менее 1 из 20 вашего теста потерпит неудачу, используйте исключения cast +.
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)
В лучшем случае приведение происходит лишь незначительно (около 10%). Предполагая, что это различие подходит для обобщения (я не думаю, что это так), тогда точка безубыточности находится где-то между 200 и 250 прогонами, и только 1 вызывает исключение.
Таким образом, исключения должны использоваться только тогда, когда происходят действительно исключительные вещи, это решение для вас и вашей базы кода. Когда они не используют код, они могут быть проще и быстрее.
Если производительность не имеет значения, вам, вероятно, следует просто следовать тем соглашениям, которые у вас уже есть в команде или кодовой базе, и игнорировать все эти ответы.