--Multipart_Fri_Apr_25_11:49:43_2003-1
Content-Type: text/plain; charset=ISO-2022-JP

なかだです。

At Thu, 24 Apr 2003 02:38:48 +0900,
Nobuyoshi-Nakada wrote:
> http://www.cwi.nl/~cilibrar/floatingpointconv.pdf
> http://ftp.ccs.neu.edu/pub/people/will/howtoread.ps

上記のBellerophonとAlgorithmRを、試しにRubyで実装してみました。
しかしこれ、SchemeとかRubyならいいけど、CだとBignumが面倒なこと
になりな。

# ついでにデバッグ用のFloatの16進変換も。


--Multipart_Fri_Apr_25_11:49:43_2003-1
Content-Type: text/x-ruby; charset=US-ASCII
Content-Disposition: attachment; filename="bellerophon.rb"
Content-Transfer-Encoding: 7bit

# $Id: bellerophon.rb,v 1.1 2003/04/25 02:45:07 nobu Exp $

class Float
  def split
    m, k  ath.frexp(abs())
    [self <0, Math.ldexp(m, MANT_DIG).to_i, k - DIG]
  end

  def significand
    Math.ldexp(Math.frexp(self)[0], MANT_DIG).to_i
  end

  def exponent
    Math.frexp(self)[1] - MANT_DIG
  end

  def prev_delta
    m, e  ath.frexp(self)
    self - Math.ldexp(m 0.5 ? 0.5 : 1.0, e - MANT_DIG)
  end

  def succ_delta
    m, e  ath.frexp(self)
    self + Math.ldexp(m 0.5 ? 0.5 : 1.0, e - MANT_DIG)
  end
end

class Integer
  N  loat::MANT_DIG
  P  (Float::MANT_DIG+16)&~15)
  TWO_P_N_1  <<(P-Float::MANT_DIG-1)
  extra_prec   - Float::MANT_DIG
  EXTRA_PREC_MASK  1 << extra_prec) - 1
  TWO_N  <<Float::MANT_DIG
  TWO_N_1  <<(Float::MANT_DIG-1)
  LOG5_OF_TWO_N  (Float::MANT_DIG*Math.log(2))/Math.log(5)).ceil
  H  3
  H2   < LOG5_OF_TWO_N ? H : LOG5_OF_TWO_N

  def to_float(e  )
    return 0.0 if self.zero?
    return -(-self).bellerophon(e) if self < 0
    if self < TWO_N
      return to_f() if e.zero?
      return e > 0 ? (to_f() * 10**e) : (to_f() / 10**-e) if e.abs < H2
      slop  
    else
      slop  
    end
    slop +  if e < 0 or e > 
    z  o_f() * 10**e
    if ((z.significand & EXTRA_PREC_MASK) - TWO_P_N_1).abs > slop
      return z
    end
    e10  0**(e.abs)
    while true
      m  .significand
      k  .exponent
      x  elf
      y  
      if e < 0
        y * 10
      else
        x * 10
      end
      if k < 0
        x << k
      else
        y << 
      end
      d   - y
      d2   * m * d.abs
      if d2 < y
        break unless m TWO_N_1 and d < 0 and 2*d2 > y
        z  .prev_delta
      elsif d2 y and (m & 1).zero?
        break unless m TWO_N_1 and d < 0
        z  .prev_delta
      elsif d < 0
        z  .prev_delta
      elsif d > 0
        z  .succ_delta
      else
        break
      end
    end
    z
  end
end

--Multipart_Fri_Apr_25_11:49:43_2003-1
Content-Type: text/x-ruby; charset=US-ASCII
Content-Disposition: attachment; filename="hexfloat.rb"
Content-Transfer-Encoding: 7bit

# $Id: hexfloat.rb,v 1.1 2003/04/25 02:45:07 nobu Exp $

class Float
  def hex
    return "nan" if nan?
    case infinite?
    when 1
      return "inf"
    when -1
      return "-inf"
    end
    s  elf < 0 ? "-0x" : "0x"
    m, e  ath.frexp(abs())
    m  ath.ldexp(m, n  (e - 1) & 3) + 1)
    e - 
    n  .floor
    s << "%x" % n
    if (m - ) > 0
      s << "."
      begin
        s << "%.4x" % (n  m * x10000).floor)
      end while (m - ) > 0
    end
    s.sub!(/0+$/, '')
    e.zero? or s << "p%+d" % e
    s
  end

  def bin
    [self].pack("G").gsub(/./) {|s| "%.2x" % s[0]}
  end
end

class String
  alias to_float to_f
  def to_f
    return to_float() unless m  \A\s*([-+])?0x/i.match(self)
    sign  [1]
    if m  \A([[:xdigit:]]+)(?:\.([[:xdigit:]]+))?(?:p([-+]\d+))?/i.match(m.post_match)
      f  [1]
      e  [3].to_i
      if m[2]
        f << m[2]
        e - *m[2].size
      end
      f  .to_i(16)
      f  ath.ldexp(f, e)
    else
      f  .0
    end
    sign '-' ? -f : f
  end
end

--Multipart_Fri_Apr_25_11:49:43_2003-1
Content-Type: text/plain; charset=ISO-2022-JP


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

--Multipart_Fri_Apr_25_11:49:43_2003-1--