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


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

<p class="codepen" data-height="600" data-default-tab="result" data-slug-hash="YPKmWbm" data-pen-title="Untitled" data-user="ikiuo" style="height: 600px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ikiuo/pen/YPKmWbm">
  Untitled</a> by Ikiuo (<a href="https://codepen.io/ikiuo">@ikiuo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

# HTML単体版

<details><summary>HTML ファイル(長いので折りたたみ)</summary><div>

```JavaScript: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>
```

</div></details>

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

https://qiita.com/ikiuo/items/7c623c05bf550c683426