开发者

Why does Ruby give this large precision decimal result?

开发者 https://www.devze.com 2023-03-10 10:39 出处:网络
I want to convert a subtitle time code: begin=\"00:00:07.71\" dur=\"00:00:03.67 to pure seconds: begin=7.1 end=11.38

I want to convert a subtitle time code:

begin="00:00:07.71" dur="00:00:03.67

to pure seconds:

begin=7.1 end=11.38

I wrote a Ruby code:

def to_sec(value)
        a = value.split(':')
        a[0].to_i*3600+a[1].to_i*60+a[2].to_f
    end

which resulted in 11.379999999999999. Can anybody tell me why this happens? Is there any Time library that can do this开发者_如何学JAVA conversion?


It'll probably be easiest for you to represent your underlying datatype as integer hundredths of a second (centiseconds):

     def to_csec(value) #if you had CSec < Integer this would be `def self.[](value)`
        a = value.split(':')
        #tacking on a couple zeros to each
        a[0].to_i*360000+a[1].to_i*6000+(a[2].to_f * 100).to_i
     end

You could add some helpers for dealing with the durations and pretty printing them as well:

     def csec_to_s(csec) #if you had CSec < Integer, this would be `def to_sec`
        "%.2f" % (csec.to_f / 100)
     end

    class SubtitleDuration < Range
     def initialize(a,b)
        centi_a = to_csec(a)
        super(centi_a,to_csec(b) + centi_a)
     end
     def to_s
       "begin=#{csec_to_s(self.begin)} end=#{csec_to_s(self.end) }"
     end
    end

Then your answer is just:

    puts SubtitleDuration.new("00:00:07.71", "00:00:03.67").to_s 
    #=> begin=7.71 end=11.38


This sort of thing can happen in just about any programming language. It's because of how floating point numbers are represented. They're not stored as decimals under the hood, so sometimes you get odd rounding errors like this.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号