0
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?

IEEE 754 倍精度浮動小数点数 詳細表示

Last updated at Posted at 2025-02-07

文字列を Number(JavaScript) 型に変換して詳細を出力します。
C/C++ double 型, Python float 型も同じ形式です。

See the Pen Untitled by Ikiuo (@ikiuo) on CodePen.

HTML単体版

HTML ファイル(長いので折りたたみ)
sample.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>IEEE 754 倍精度浮動小数点数 詳細表示</title>
    <style>
     body {
         width: 40em;
         margin: auto;
     }
     table {
         border: solid 1px #e2e2e2;
         border-collaspe: collaspe;
         border-spacing: 0;
     }
     th, td { border: solid 1px #e2e2e2; }
     td { padding: 2px; }
     .left { text-align: left; }
     .center { text-align: center; }
     .right { text-align: right; }
     .small { font-size: small; }
     .xsmall { font-size: x-small; }
     .ntext {
         max-width: 30em;
         word-break: break-all;
     }
    </style>
  </head>
  <body>
    <h3>IEEE 754 倍精度浮動小数点数 詳細表示</h3>
    <div>
      <textarea id="tagNumber" cols="72" rows="5"
                placeholder="数値を入力してください(改行または','区切りで複数可)"
                oninput="onUpdate(value)"></textarea>
    </div>
    <div class="xsmall"><span id="tagClipboard">&nbsp;</span></div>
    <div>&nbsp;</div>
    <code id="tagOutput"></code>

    <script>

     function toString(number, width, base) {
         return ('0'.repeat(width) + number.toString(base)).slice(-width);
     }

     const insNbsp4 = (s => [...s].join('&nbsp;'.repeat(4)));

     function digrp(s, w) {
         const n = s.length;
         if (n == 0) return s;
         const c = Math.trunc((n - 1) / w);
         const p = (i => Math.max(0, n - w * i));
         const t = [...Array(c + 1)].map((_, i) => s.slice(p(i + 1), p(i)));
         t.reverse();
         return t;
     }

     function digrps(s, w, t) {
         if (t == null)
             t = '&nbsp;';
         return digrp(s, w).join(t);
     }

     function pow5n(n) {
         var a = 1n;
         var b = 5n;
         while (n) {
             if (n & 1)
                 a *= b;
             b *= b;
             n >>= 1;
         }
         return a;
     }
     const DBL_DEC_MAX = 1023 + 52 - 1;
     const POW5FX = pow5n(DBL_DEC_MAX);

     function parsef64(num) {
         const view = new DataView(new ArrayBuffer(8));
         view.setFloat64(0, num, true);
         const bin = view.getBigInt64(0, true) & ((1n << 64n) - 1n);
         const sign = bin >> 63n;
         const exp = (bin >> 52n) & 0x7ffn;
         const man = bin & 0xfffffffffffffn;
         const xman = (exp ? (1n << 52n) : 0n) | man;
         return {num, bin, sign, exp, man, xman}
     }

     function ieee754info(f64i) {
         const hex = toString(f64i.bin, 16, 16);
         const sign = f64i.sign;
         const exp = f64i.exp;
         const man = f64i.man;
         return [
             '<tr class="xsmall">', '<th>&nbsp;</th>',
             '<th>符号</th>',
             '<th>指数部</th>',
             '<th>仮数部</th>',
             '</tr>',
             '<tr class="xsmall">', '<th>16進</th>',
             `<td colspan="2" class="right" onclick="toClipboard('0x${hex}')">${hex.slice(0,3)}</td>`,
             `<td class="left" onclick="toClipboard('0x${hex}')">${hex.slice(3)}</td>`,
             '</tr>',
             '<tr class="xsmall">', '<th>16進</th>',
             `<td class="center">${sign}</td>`,
             `<td class="right">&nbsp;&nbsp;${insNbsp4(toString(exp, 3, 16))}</td>`,
             `<td>&nbsp;&nbsp;&nbsp;${insNbsp4(toString(man, 13, 16))}</td>`,
             '</tr>',
             '<tr class="xsmall">', '<th>2進</th>',
             `<td class="center">${sign}</td>`,
             `<td class="right">${digrps(toString(exp, 11, 2), 4)}</td>`,
             `<td>${digrps(toString(man, 52, 2), 4)}</td>`,
             '</tr>',
             '<tr class="xsmall">', '<th>10進</th>',
             `<td class="center">${sign}</td>`,
             `<td class="right">(${exp - 1023n}) ${exp}</td>`,
             `<td class="left">${man}</td>`,
             '</tr>',
         ].join('');
     }

     function fullprec(f64i) {
         if (f64i.exp == 2047)
             return f64i.num.toString();
         const ep = f64i.exp > 0n ? f64i.exp - 1n : 0n;
         const fx = (f64i.xman << ep) * POW5FX;
         const tmp = '' + fx;
         const tlen = 1 + DBL_DEC_MAX - tmp.length;
         const tval = '0'.repeat(tlen < 0 ? 0 : tlen) + tmp;
         const sint = tval.slice(0, -DBL_DEC_MAX);
         const sdec = tval.slice(-DBL_DEC_MAX).replace(/0+$/, '');
         return (f64i.sign ? '-' : '') + (sdec.length ? `${sint}.${sdec}` : sint);
     }

     function hexstr(f64i) {
         if (f64i.num == 0 || f64i.exp == 2047)
             return f64i.num.toString();
         const sign = f64i.sign ? '-' : '';
         const one = (f64i.man != f64i.xman) ? 1n : 0n;
         const hex = ('0'.repeat(13) + f64i.man.toString(16)).slice(-13);
         const exp = f64i.exp - (1022n + one);
         return `${sign}0x${one}.${hex}p${exp >= 0 ? '+' : ''}${exp}`;
     }

     function parseNumber(inp) {
         const n = Number(inp);
         if (!isNaN(n))
             return n;

         var sign = 1.0;
         var linp = inp.trim().toLowerCase();
         switch (linp[0]) {
             case '-': sign = -1.0;
             case '+': linp = linp.slice(1);
             default: break;
         }
         if (linp.slice(0, 2) != '0x')
             return n;

         const hinp = linp.slice(2).split('p', 2);
         const hnum = hinp[0];

         var hexp = 0;
         if (hinp.length == 2) {
             const t = hinp[1];
             if (t.length == 0)
                 return n;
             hexp = Number(t);
             if (!isFinite(hexp) || hexp != Math.trunc(hexp))
                 return n;
         }

         const hdot = hnum.split('.', 2);
         const hint = hdot[0];
         if (hint.length == 0)
             return n;
         const hdec = hdot.length == 1 ? '' : hdot[1];
         const hval = Number(`0x${hint}${hdec}`, 16);
         if (!isFinite(hval))
             return n;

         return sign * hval * Math.pow(2, hexp - hdec.length * 4);
     }

     function numberInfo(inp) {
         inp = inp.trim();
         if (!inp.length)
             return '';
         const num = parseNumber(inp);
         const exp = num.toExponential();
         const f64i = parsef64(num);
         const fpn = fullprec(f64i);
         const hex = hexstr(f64i);
         return [
             '<table>',
             '<tr style="background-color: #efe;">',
             '<th colspan="2" style="min-width: 5em;">入力文字列</th>',
             `<td colspan="2" class="ntext">${inp}</td>`,
             // `<td colspan="2"><textarea disabled cols="62" rows="2">${inp}</textarea></td>`,
             '</tr>',
             '<tr>',
             '<th colspan="2">既定表示</th>',
             `<td colspan="2" onclick="toClipboard('${num}')">${num}</td>`,
             '</tr>',
             '<tr>',
             '<th colspan="2">指数表示</th>',
             `<td colspan="2" onclick="toClipboard('${exp}')">${exp}</td>`,
             '</tr>',
             '<tr>',
             '<th colspan="2">16進形式</th>',
             `<td colspan="2" onclick="toClipboard('${hex}')">${hex}</td>`,
             '</tr>',
             '<tr>',
             '<th colspan="2">厳密値</th>',
             `<td colspan="2" class="ntext" onclick="toClipboard('${fpn}')">${fpn}</td>`,
             // `<td colspan="2"><textarea readonly cols="62" rows="5" onclick="toClipboard('${fpn}')">${fpn}</textarea></td>`,
             '</tr>',
             '<tr><th colspan="4" class="xsmall">IEEE 754 倍精度浮動小数点数 詳細</th></tr>',
             ieee754info(f64i),
             '</table>',
             '<div>&nbsp;</div>',
         ].join('');
     }

     function toClipboard(text) {
         navigator.clipboard.writeText(text).then(() => {
             if (text.length >= 80)
                 text = text.slice(0, 77) + '⋅⋅⋅';
             tagClipboard.innerText = 'クリップボードへコピー:' + text;
         }, () => {
             tagClipboard.innerText = 'クリップボードへのコピー失敗';
         });
     }

     function onUpdate(inp) {
         tagOutput.innerHTML =
             inp.split('\n').map(s => s.split(',')).flat()
                .map(v => numberInfo(v)).join('');
     }

     window.onload = (() => onUpdate('0'));

    </script>
  </body>
</html>

半精度/単精度/倍精度/四倍精度 版はこちら

0
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
0
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?