1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

単精度浮動小数点数

Last updated at Posted at 2024-08-26

導入

単精度浮動小数点数を扱うプログラムで書くことで、単精度浮動小数点数の内部表現についての理解を深めます。

プログラム

(use srfi-13)

(define nil '())

(define (digit->integer c)
  (- (char->integer c) (char->integer #\0)))

;;

(define (number->bns num)
  (format #f "~32,'0b" num))

(define (bns->float bns)
  (let ((s (get-s bns))
        (e (get-e bns))
        (m (get-m bns)))
    (* s m (expt 2 (- e 127)))))

(define (get-s bns)
  (let ((val (string->number (substring bns 0 1) 2)))
    (if (= val 0)
        1
        -1)))

(define (get-e bns)
  (string->number (substring bns 1 9) 2))

(define (get-m bns)
  (bns->binary (substring bns 9 32)))

(define (bns->binary bns)
  (define (iter lst k val)
    (if (null? lst)
        val
        (iter (cdr lst)
              (/ k 2)
              (if (= (car lst) 1) (+ val k) val))))
  (iter (map digit->integer (string->list bns)) 0.5 1))

(define (dec->num dec)
  (define (iter lis val)
    (if (null? lis)
        val
        (iter (cdr lis) (+ (* 2 val) (car lis)))))
  (iter (map digit->integer (string->list dec)) 0))

(define (round-dec dec-pt)
  (let ((lsd (string->number (substring dec-pt 23 24)))
        (dec (substring dec-pt 0 23)))
    (if (= lsd 0)
        dec
        (let ((rd (+ (dec->num dec) lsd)))
          (if (>= rd #xFFFFFF)
              dec
              (format #f "~23,'0b" rd))))))

(define (decimal->bin d k bin)
  (if (or (> k 24) (= d 0))
      bin
      (let* ((s (string-split (number->string (* d 2)) "."))
             (i (car s))
             (nd (cadr s)))
        (decimal->bin (string->number (string-append "0." nd)) (+ k 1) (string-append bin i)))))

(define (integer-part str)
  (format #f "~b" (string->number str)))

(define (decimal-part str)
  (decimal->bin str 0 ""))

(define (optimize-hex f)
  (define (opt-int int-pt dec-pt)
    (cons
     (+ 127 (- (string-length int-pt) 1))
     (round-dec (string-pad-right (string-append (substring int-pt 1 (string-length int-pt)) dec-pt) 24 #\0))))
  (define (opt-dec dec-pt)
    (define (iter d k)
      (if (or (null? d) (= (car d) 1))
          (cons (- 127 k)
                (round-dec (string-pad-right (substring dec-pt k (string-length dec-pt)) 24 #\0)))
          (iter (cdr d) (+ k 1))))
    (iter (map digit->integer (string->list dec-pt)) 1))
  (let* ((v (if (< f 0) (* -1 f) f))
         (s (string-split (number->string v) "."))
         (i (car s))
         (d (string->number (string-append "0." (cadr s)))))
    (let* ((int-pt (integer-part i))
           (dec-pt (decimal-part d)))
      (if (> (string->number int-pt) 0)
          (opt-int int-pt dec-pt)
          (opt-dec dec-pt)))))

(define (bns->hex bns)
  (define (iter lst hex)
    (if (null? lst)
        hex
        (iter (cddddr lst)
              (string-append
               hex
               (format #f "~x"
                       (+ (* 8 (car lst))
                          (* 4 (cadr lst))
                          (* 2 (caddr lst))
                          (cadddr lst)))))))
  (iter (map digit->integer (string->list bns)) ""))

;; IEEE 標準形式(単精度) 16->2 進数変換
(define (hex->float hex)
  (inexact (bns->float (number->bns hex))))

;; IEEE 標準形式(単精度) 2->16 進数変換
(define (float->hex f)
  (let* ((s (if (< f 0) "1" "0"))
         (h (optimize-hex f))
         (e (car h))
         (m (cdr h)))
    (bns->hex
     (string-append s
                    (format #f "~8,'0b" e)
                    m))))

実行例

1.

gosh> (float->hex (* (hex->float #x40a80000) (hex->float #xc0300000)))
"c1670000"

2.

gosh> (+ (hex->float #xC12C0000) (hex->float #x40A40000))
-5.625

参考文献

実行例1 ... 技術士一次試験 平成27年度 専門科目 III-32
実行例2 ... 技術士一次試験 平成23年度 専門科目 IV-8

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?