[RUBY-ON-RAILS] 문자열이 유효한 부동 소수점 값이 있는지 확인
RUBY-ON-RAILS문자열이 유효한 부동 소수점 값이 있는지 확인
문자열 값이 유효한 부동 소수점 값이 경우 단순히 확인하는 방법이있다. 이 숫자 값이 아닌 경우 문자열에 to_f 호출하면 0.0으로 변환됩니다. 그것은 가까이 내가 원하는 것입니다 잘못된 플로트 문자열을 전달,하지만 난 예외를 잡기 처리하지 않을 때 플로트 ()를 사용하면 예외를 발생시킵니다. 유모와 같은 방법은 내가 정말 원하는 무엇입니까? Float 클래스에 존재를 수행하지만 숫자가 아닌 문자열이 0.0 (사용 to_f)로 변경하지 않고 float로 변환 할 수 없기 때문에 그 도움이되지 않는다.
"a".to_f => 0.0
"a".to_f.nan? => false
Float("a") => ArgumentError: invalid value for Float(): "a"
이것에 대한 간단한 해결책이 있습니까 아니면 문자열이 유효한 부동 소수점 값이 있는지 확인하는 코드를 작성해야합니까?
해결법
-
==============================
1.루비의 세계에 대한 흥미로운 사실은 순수 루비의 대부분은 루비와 표준 라이브러리를 구현하는 Rubinius 프로젝트의 존재이다. 그 결과, 그들은과 같은 커널 # 플로트의 순수 루비 구현이 :
루비의 세계에 대한 흥미로운 사실은 순수 루비의 대부분은 루비와 표준 라이브러리를 구현하는 Rubinius 프로젝트의 존재이다. 그 결과, 그들은과 같은 커널 # 플로트의 순수 루비 구현이 :
def Float(obj) raise TypeError, "can't convert nil into Float" if obj.nil? if obj.is_a?(String) if obj !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/ raise ArgumentError, "invalid value for Float(): #{obj.inspect}" end end Type.coerce_to(obj, Float, :to_f) end
이것은)가 플로트 (실행될 때 루비가하는 내부 작업과 일치하는 정규 표현식을 제공하지만, 예외없이. 당신이 지금 할 수있는 그래서 :
class String def nan? self !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/ end end
이 솔루션의 좋은 점은 그 Rubinius 실행 이후, 그리고 RubySpec, 당신은 루비 자체 처리하는이 정규식 핸들을 가장자리 케이스를 알고 전달하고 당신은 어떤 두려움없이 문자열에 to_f 호출 할 수 있습니다!
-
==============================
2.여기에 한 가지 방법이다 :
여기에 한 가지 방법이다 :
class String def valid_float? # The double negation turns this into an actual boolean true - if you're # okay with "truthy" values (like 0.0), you can remove it. !!Float(self) rescue false end end "a".valid_float? #false "2.4".valid_float? #true
당신은 문자열의 원숭이 패치를 피하고 싶은 경우에, 당신은 항상 당신은 물론, 제어 일부 모듈의 클래스 메소드 만들 수 있습니다 :
module MyUtils def self.valid_float?(str) !!Float(str) rescue false end end MyUtils.valid_float?("a") #false
-
==============================
3.
# Edge Cases: # numeric?"Infinity" => true is_numeric?"Infinity" => false def numeric?(object) true if Float(object) rescue false end #Possibly faster alternative def is_numeric?(i) i.to_i.to_s == i || i.to_f.to_s == i end
-
==============================
4.나는 정규식 대 캐스트 + 예외에 해결되지 않은 토론을보고 난 벤치 마크 모든 것을 시도하고 객관적인 답을 생산할 것이라고 생각 :
나는 정규식 대 캐스트 + 예외에 해결되지 않은 토론을보고 난 벤치 마크 모든 것을 시도하고 객관적인 답을 생산할 것이라고 생각 :
다음은 각 방법의 최악의 여기 시도와 최상의 경우의 소스는 다음과 같습니다
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 다음과 같은 결과 :
우리는 선형 시간 알고리즘을 처리하고 있기 때문에 나는 우리가 일반화를 만들기 위해 경험적인 측정을 사용할 생각합니다. 그 정규식이 더 일관성을 쉽게 확인할 수와 문자열의 길이에 따라 약간 통과 변동 만합니다. 훨씬 느린 실패가있을 때 거기에는 실패없고, 때 캐스트 빨리 명확하다.
우리가 성공 시간을 비교하면 우리는 캐스트 최상의 경우는 빠른 정규식 최상의 경우보다 0.3 초에 대한 것을 볼 수 있습니다. 우리의 경우 최악의 경우 시간의 양이 나누면 우리는 심지어 예외 정규식 속도에 맞게 캐스트 아래로 둔화와 함께 휴식을 취할 얼마나 많은 실행 추정 할 수있다. 육초가 0.3로 다이빙에 대해 성능 문제 및 다음 사용 캐스트 + 예외를 실패하는 테스트의 20 미만을 기대한다면 20 그래서에 대한 정보를 제공합니다.
JRuby를 1.7.4 완전히 다른 결과가 있습니다 :
캐스트는 소폭 빠르게 최선의 경우 (10 % 약)입니다. 이 차이를 추정하는 것은 (내가 생각하지 않습니다) 일반화하기에 적합하고 휴식도 포인트는 1 예외의 원인이 어딘가에 200과 250 실행 사이입니다.
정말 예외적 인 상황이 발생하면 예외에만 사용해야합니다 그래서, 이것은 당신과 당신의 코드베이스에 대한 결정이다. 그들은 코드를 사용하지 않을 때 그들은 간단하고 빠르게 할 수 있습니다에 있습니다.
성능이 중요하지 않습니다 경우 팀 또는 코드베이스가 이미 가지고 있으며,이 모든 답을 무시 어떤 규칙, 당신은 아마 다음과 같은 것이다.
-
==============================
5.음, 당신은 아마도 예외를 원하지 않는 경우 :
음, 당신은 아마도 예외를 원하지 않는 경우 :
def is_float?(fl) fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/ end
영업 이익 때문에 특별히 예외없이 해결책을 요구했다. 정규 표현식 기반 솔루션은 소폭 느립니다 :
require "benchmark" n = 500000 def is_float?(fl) !!Float(fl) rescue false end def is_float_reg(fl) fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/ end Benchmark.bm(7) do |x| x.report("Using cast") { n.times do |i| temp_fl = "#{i + 0.5}" is_float?(temp_fl) end } x.report("using regexp") { n.times do |i| temp_fl = "#{i + 0.5}" is_float_reg(temp_fl) end } end
결과 :
5286 snippets:master!? % user system total real Using cast 3.000000 0.000000 3.000000 ( 3.010926) using regexp 5.020000 0.000000 5.020000 ( 5.021762)
-
==============================
6.이 시도
이 시도
def is_float(val) fval = !!Float(val) rescue false # if val is "1.50" for instance # we need to lop off the trailing 0(s) with gsub else no match return fval && Float(val).to_s == val.to_s.gsub(/0+$/,'') ? true:false end s = "1000" is_float s => false s = "1.5" is_float s => true s = "Bob" is_float s => false n = 1000 is_float n => false n = 1.5 is_float n => true
-
==============================
7.
def float?(string) true if Float(string) rescue false end
이 지지체는 1.5, 5, 123.456, 1_000 아니지만 1000, 1000 등 (예를 들어 동일한 문자열 to_f # 1 등).
>> float?("1.2") => true >> float?("1") => true >> float?("1 000") => false >> float?("abc") => false >> float?("1_000") => true
출처 : https://github.com/ruby/ruby/blob/trunk/object.c#L2934-L2959
-
==============================
8.나는 주석으로이 문제를 추가하려고하지 않습니다하지만 분명히 댓글 거기에 서식한다 :
나는 주석으로이 문제를 추가하려고하지 않습니다하지만 분명히 댓글 거기에 서식한다 :
반면에, 왜처럼 전환 기능으로 그것을 사용하지
class String def to_float Float self rescue (0.0 / 0.0) end end "a".to_float.nan? => true
이는 물론 당신이 처음에하고 싶지 않은 것입니다. 나는 대답은, 추측 "당신이 그렇게 왜 당신이, 당신이 정말로 예외 처리를 사용하지 않으려면 자신의 함수를 작성해야하지만?"
-
==============================
9.루비 2.6 플로트하는 새로운 예외 키워드 인수를 추가했다.
루비 2.6 플로트하는 새로운 예외 키워드 인수를 추가했다.
문자열이 유효한 플로트가 단순하게있다가 포함되어 있는지 여부 그래서, 지금 확인 :
Float('22.241234', exception: false) # => 22.241234 Float('abcd', exception: false) # => nil
from https://stackoverflow.com/questions/1034418/determine-if-a-string-is-a-valid-float-value by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 사용 레일에 JS-UJS 모듈 (레일 6 webpacker) (0) | 2020.03.03 |
---|---|
[RUBY-ON-RAILS] 레일 - 렌더링 : 대상 앵커 태그에 행동을? (0) | 2020.03.03 |
[RUBY-ON-RAILS] 유효성 검사 고유성만을 조건의 경우 레일 (0) | 2020.03.03 |
[RUBY-ON-RAILS] OS-X는 레일 : "빌드 보석 네이티브 확장에 실패" (0) | 2020.03.03 |
[RUBY-ON-RAILS] 레일 : 어떻게 특정 시간대에 날짜 - 시간 문자열을 구문 분석 (0) | 2020.03.03 |