0
1

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 浮動小数点数 詳細表示 (binary 16/32/64/128)

Last updated at Posted at 2025-02-21

こちらは倍精度のみだったので様々な精度に対応したものを作ってみた。

  • binary16
    • シェーディング言語など
  • binary32
    • C/C++ の float 型
  • binary64
    • C/C++ の double 型
    • Python の float 型
    • JavaScript の Number 型
  • binary128
    • 普及するのは何時だろう?

拡張倍精度(80ビット)は非対応です。

See the Pen IEEE 754 浮動小数点数 詳細表示 by Ikiuo (@ikiuo) on CodePen.

HTML単体版

HTML ファイル(長いので折りたたみ)
sample.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>IEEE 754 浮動小数点数 詳細表示</title>
    <style>
     table {
         border: none;
         border-collapse: collapse;
         overflow-x: auto;
     }
     th, td {
         border: 1px solid #dfdfdf;
         padding: 2px 4px;
     }

     .left { text-align: left; }
     .center { text-align: center; }
     .right { text-align: right; }
     .vtop { vertical-align: top; }

     .large { font-size: large; }
     .small { font-size: small; }
     .xsmall { font-size: x-small; }
     .xxsmall { font-size: xx-small; }

     .ctext:hover {
         cursor: pointer;
         background-color: #e2e2e2;
     }
     .ftext { color: #006; }
     .htext { color: #600; }
     .ntext {
         word-break: break-all;
     }

     .eline { background: #edefef; }
     .oline { background: #f5f6f6; }

     .inpdata { background: #f5ffff; }
    </style>
  </head>
  <body>

    <script>

     const LOG10_2 = 0.3010299956639812;

     const gAbs = ((a, b) => a >= b ? a - b : b - a);

     function power5n(n) {
         var a = 1n;
         var b = 5n;
         while (n) {
             if (n & 1)
                 a *= b;
             b *= b;
             n >>= 1;
         }
         return a;
     }
     const power10n = (n => power5n(n) << BigInt(n));

     const BitLength = (x => x ? x.toString(2).length : 0);

     const toString16N = ((v, n) => {
         const l = Number(n);
         return ('0'.repeat(l) + v.toString(16)).slice(-l);
     });
     const toString16B = ((v, b) => toString16N(v, (b + 3n) >> 2n));

     /*
      * 分数表現型
      */
     class FractionBI {
         #S;

         nan;         // 非数のとき true
         finite;      // 有限値のとき true
         sign;        // 負のとき true
         numerator;   // 分子 (BigInt)
         denominator; // 分母 (BigInt)

         constructor(value) {
             const S = FractionBI;
             this.#S = S;

             switch (typeof value) {
                 case 'bigint':
                     this.#fromBigInt(value);
                     break;
                 case 'number':
                     this.#fromNumber(value);
                     break;
                 case 'string':
                     this.#fromString(value);
                     break;
                 default:
                     if (FractionBI.prototype.isPrototypeOf(value)) {
                         this.#fromRational(value);
                         break;
                     }
                     throw new Error("invalid type", {cause: value});
             }
         }

         // 非数を設定
         #setNaN(sign) {
             this.nan = true;
             this.finite = false;
             if (sign != null)
                 this.sign = sign;
             this.numerator = null;
             this.denominator = null;
         }

         // 無限大を設定
         #setInfinity(sign) {
             this.nan = false;
             this.finite = false;
             if (sign != null)
                 this.sign = sign;
             this.numerator = null;
             this.denominator = null;
         }

         // 有限値を設定
         #setFinite(sign, numerator, denominator) {
             if (!denominator)
                 throw new Error("invalid denominator", {cause: denominator});

             this.nan = false;
             this.finite = true;
             if (sign != null)
                 this.sign = sign;

             let fnum = numerator;
             let fden = denominator;
             if (fnum) {
                 while ((fnum % 5n) == 0n &&
                        (fden % 5n) == 0n) {
                     fnum /= 5n;
                     fden /= 5n;
                 }

                 const t = (fnum | fden);
                 const s = BigInt(BitLength(t & -t) - 1);
                 fnum >>= s;
                 fden >>= s;
             }
             this.numerator = fnum;
             this.denominator = fden;
         }

         // 0 を設定
         #setZero(sign) {
             this.nan = false;
             this.finite = true;
             if (sign != null)
                 this.sign = sign;
             this.numerator = 0n;
             this.denominator = 1n;
         }

         // FractionBI のコピー
         #fromRational(value) {
             this.nan = value.nan;
             this.finite = value.finite;
             this.sign = value.sign;
             this.numerator = value.numerator;
             this.denominator = value.denominator;
         }

         // BigInt 型を変換
         #fromBigInt(value) {
             this.nan = false;
             this.finite = true;
             this.sign = (value < 0n);
             this.numerator = (value < 0n) ? -value : value;
             this.denominator  = 1n;
         }

         // Number 型を変換
         #fromNumber(value) {
             const mb64 = (1n << 64n) - 1n;
             const mexp = ((1n << 11n) - 1n);
             const mman = ((1n << 52n) - 1n);

             const view = new DataView(new ArrayBuffer(8));
             view.setFloat64(0, value, true);

             const bin = mb64 & view.getBigInt64(0, true);
             const sign = (1n & (bin >> 63n));
             const exp = mexp & (bin >> 52n);
             const man = mman & bin;

             const fsign = sign != 0n;
             if (exp == 0n && man == 0n) {
                 this.#setFinite(fsign, 0n, 1n);
                 return;
             }
             if (exp == mexp) {
                 if (mman != 0)
                     this.#setNaN(fsign);
                 else
                     this.#setInfinity(fsign);
                 return;
             }

             const nnum = man | (exp ? (1n << 52n) : 0n);
             const nden = 1n << (exp ? 52n : 51n);
             const fnum = nnum << (exp > 1023n ? exp - 1023n : 0n);
             const fden = nden << (exp < 1023n ? 1023n - exp : 0n);
             this.#setFinite(fsign, fnum, fden);
         }

         // 文字列から変換
         #fromString(text) {
             const S = this.#S;

             text = text.trim().toLowerCase();

             let fsign = false;
             let fnum = 0n;
             let fden = 1n;

             let tpos = 0;
             if (tpos >= text.length) {
                 this.#setNaN(fsign);
                 return;
             }

             switch (text[tpos]) {
                 case '-':
                     fsign = true;
                     // FALLTHROUGH
                 case '+':
                     if (++tpos < text.length)
                         break;
                     this.#setNaN(fsign);
                     return;
             }

             switch (text.slice(tpos)) {
                 case 'nan':
                     this.#setNaN(fsign);
                     return;

                 case 'inf':
                 case 'infinity':
                     this.#setInfinity(fsign);
                     return;
             }

             const dtab = S.#base10Table;
             let btab = dtab;
             let base = 10n;

             if (tpos >= text.length) {
                 this.#setNaN(fsign);
                 return;
             }
             if (text[tpos] == '0') {
                 if (++tpos >= text.length) {
                     this.#setFinite(fsign, fnum, fden);
                     return;
                 }
                 switch (text[tpos]) {
                     case 'b':
                         btab = S.#base2Table;
                         base = 2n;
                         break;
                     case 'o':
                         btab = S.#base8Table;
                         base = 8n;
                         break;
                     case 'x':
                         btab = S.#base16Table;
                         base = 16n;
                         break;
                 }
                 if (base != 10n) {
                     if (++tpos >= text.length) {
                         this.#setNaN(fsign);
                         return;
                     }
                 }
             }

             let dot = false;
             for (;; tpos++) {
                 if (tpos >= text.length) {
                     this.#setFinite(fsign, fnum, fden);
                     return;
                 }

                 const c = text[tpos];
                 const n = btab[c];

                 if (n != null) {
                     fnum = fnum * base + n;
                     if (dot)
                         fden *= base;
                     continue;
                 }
                 if (c == '_' || c == ',')
                     continue;
                 if (c != '.')
                     break;
                 if (dot) {
                     this.#setNaN(fsign);
                     return;
                 }
                 dot = true;
             }

             let expm = base;
             switch (text[tpos]) {
                 case 'p':
                     if (expm == 10n) {
                         this.#setNaN(fsign);
                         return
                     }
                     expm = 2n;
                     // FALLTHROUGH
                 case 'e':
                     if (++tpos < text.length)
                         break;
                     // FALLTHROUGH
                 default:
                     this.#setNaN(fsign);
                     return;
             }

             let esign = false;
             switch (text[tpos]) {
                 case '-':
                     esign = true;
                     // FALLTHROUGH
                 case '+':
                     if (++tpos < text.length)
                         break;
                     this.#setNaN(fsign);
                     return;
             }

             let xnum = 0n;
             for (; tpos < text.length; tpos++) {
                 const c = text[tpos];
                 const n = dtab[c];
                 if (n == null) {
                     this.#setNaN(fsign);
                     return;
                 }
                 xnum = xnum * 10n + n;
             }
             if (xnum >= 65536n) {
                 if (esign)
                     this.#setZero(fsign);
                 else
                     this.#setInfinity(fsign);
                 return;
             }

             let expv = 1n;
             while (xnum) {
                 if ((xnum & 1n))
                     expv *= expm;
                 expm *= expm;
                 xnum >>= 1n;
             }
             if (esign)
                 fden *= expv;
             else
                 fnum *= expv;

             this.#setFinite(fsign, fnum, fden);
         }

         static #base2Table = {
             '0': 0n, '1': 1n,
         }
         static #base8Table = {
             '0': 0n, '1': 1n, '2': 2n, '3': 3n,
             '4': 4n, '5': 5n, '6': 6n, '7': 7n,
         }
         static #base10Table = {
             '0': 0n, '1': 1n, '2': 2n, '3': 3n, '4': 4n,
             '5': 5n, '6': 6n, '7': 7n, '8': 8n, '9': 9n,
         }
         static #base16Table = {
             '0': 0n, '1': 1n, '2': 2n, '3': 3n,
             '4': 4n, '5': 5n, '6': 6n, '7': 7n,
             '8': 8n, '9': 9n, 'a': 10n, 'b': 11n,
             'c': 12n, 'd': 13n, 'e': 14n, 'f': 15n,
         }
     }

     /*
      * IEEE 754 要素
      */
     class IEEE754Parameter {

         //
         // 2進形式
         //

         static #makeBinary(exponentBits, mantissaBits) {
             const mantissaMask = (1n << mantissaBits) - 1n;
             const exponentMask = (1n << exponentBits) - 1n;
             const signPosition = exponentBits + mantissaBits;
             return {
                 mantissaBits,
                 mantissaMask,
                 mantissaPosition: 0n,
                 mantissaInt: 1n << mantissaBits,

                 exponentBits,
                 exponentMask,
                 exponentPosition: mantissaBits,
                 exponentBias: exponentMask >> 1n,

                 signBit: 1n << signPosition,
                 signPosition,

                 totalBits: signPosition + 1n,

                 getMantissa: (data => data & mantissaMask),
                 getExponent: (data => (data >> mantissaBits) & exponentMask),
                 getSign: (data => (data >> signPosition) & 1n),
             }
         }
         static #binaryCache = {
             16n: IEEE754Parameter.#makeBinary(5n, 10n),
             32n: IEEE754Parameter.#makeBinary(8n, 23n),
             64n: IEEE754Parameter.#makeBinary(11n, 52n),
             128n: IEEE754Parameter.#makeBinary(15n, 112n),
         }
         static getBinary(n) {
             const S = IEEE754Parameter;
             const bn = BigInt(n);
             const cache = S.#binaryCache
             const cached = cache[bn];
             if (cached != null)
                 return cached;
             if (bn % 32n)
                 return null;
             const nn = Number(n);
             const p = BigInt(nn - Math.round(Math.log2(nn) * 4) + 13);
             const param = S.#makeBinary(bn - p - 1n, p);
             cache[n] = param;
             return param;
         }

     }

     /*
      * IEEE 754 - 2進形式
      */
     class IEEE754Binary extends FractionBI {
         #S;
         #P;
         #round0;
         exponent;
         mantissa;

         get data() {
             const P = this.#P;
             return (this.sign ? P.signBit : 0n) |
                    (this.exponent << P.exponentPosition) |
                    this.mantissa;
         }

         get exponent2() {
             const dexp = this.exponent;
             return (dexp ? dexp : 1n) - this.#P.exponentBias;
         }

         get mantissaBits() { return this.#P.mantissaBits; }
         get exponentBits() { return this.#P.exponentBits; }
         get dataBits() { return this.#P.totalBits; }

         constructor(data_bits, value, round0) {
             super(value);
             this.#S = IEEE754Binary;
             this.#P = IEEE754Parameter.getBinary(data_bits);
             this.#round0 = Boolean(round0);
             this.#initialize();
         }

         #initialize() {
             const P = this.#P;

             if (!this.finite) {
                 this.exponent = P.exponentMask;
                 this.mantissa = this.nan ? P.mantissaInt >> 1n : 0n;
                 return;
             }

             let fnum = this.numerator;
             let fden = this.denominator;

             if (!fnum) {
                 this.exponent = 0n;
                 this.mantissa = 0n;
                 return;
             }

             const bnum = BitLength(fnum);
             const bden = BitLength(fden);
             let exp = BigInt(bnum - bden);

             if (exp >= 0)
                 fden <<= exp;
             else
                 fnum <<= -exp;
             if (fnum < fden) {
                 fnum <<= 1n;
                 exp -= 1n;
             }

             exp += P.exponentBias;
             if (exp <= 0n) {
                 fden <<= 1n - exp;
                 exp = 0n;
             }

             const xnum = fnum << P.mantissaBits;
             const xdiv = xnum / fden;
             const xrem = xnum % fden;

             const xcmp = (xrem << 1n) - fden;
             const xrnd = !this.#round0 && ((xcmp > 0n) || ((xcmp == 0n) && (xdiv & 1n))) ? 1n : 0n;

             let man = xdiv + xrnd;

             const mshift = exp > 0n ? 1n : 0n;
             if (man >= (P.mantissaInt << mshift)) {
                 man >>= mshift;
                 exp += 1n;
             }

             if (exp < P.exponentMask) {
                 this.exponent = exp;
                 this.mantissa = man & P.mantissaMask;
             } else {
                 this.finite = false;
                 this.exponent = P.exponentMask;
                 this.mantissa = 0n;
             }
         }

         #getMantissaEx() {
             return this.mantissa | (this.exponent ? this.#P.mantissaInt : 0n);
         }

         isZero() {
             return this.exponent == 0n && this.mantissa == 0n;
         }

         isPRN() {
             return this.finite && !this.isZero();
         }

         toHexData() {
             return '0x' + toString16B(this.data, this.dataBits);
         }

         #toStringSign(plus) {
             return this.sign ? '-': plus ? '+' : '';
         }

         #toStringNPRN(plus) {
             if (this.nan) return 'NaN';
             const vsign = this.#toStringSign(plus);
             if (!this.finite) return `${vsign}Infinity`;
             if (this.isZero()) return `${vsign}0`;
             return '';
         }

         static #toStringBN(dval, nexp, base) {
             const dstr = dval.toString(base);
             const mstr = '0'.repeat(Math.max(0, nexp - dstr.length)) + dstr;
             const mint = mstr.slice(0, mstr.length - nexp);
             const mdec = nexp ? mstr.slice(-nexp).replace(/0+$/, '') : '';
             const vint = mint.length ? mint : '0';
             const vdec = mdec.length ? `.${mdec}` : '';
             return vint + vdec;
         }

         static #s10ToExp(s) {
             const sign = (s[0] == '+' || s[0] == '-') ? s[0] : '';
             if (sign) s = s.slice(1);
             const dot = s.replace(/0+$/, '').split('.');
             const sint = dot[0];
             const sdec = dot[1] ?? '';
             if (sint == '0') {
                 const rdec = sdec.replace(/^0+/, '');
                 const tnum = `${sign}${rdec[0]}.${rdec.slice(1)}`;
                 const rnum = tnum.replace(/\.$/, '');
                 return `${rnum}e${rdec.length - sdec.length - 1}`;
             } else {
                 const rint = sint.replace(/^0+/, '');
                 const tnum = `${rint[0]}.${rint.slice(1)}${sdec}`;
                 const rnum = tnum.replace(/\.$/, '');
                 return `${rnum}e+${rint.length - 1}`
             }
         }

         toExponential(plus) {
             if (!this.isPRN())
                 return this.#toStringNPRN(plus);
             return this.#S.#s10ToExp(this.toString10(plus));
         }

         #toStringBF(plus, base) {
             if (!this.isPRN())
                 return this.#toStringNPRN(plus);
             const bexp = this.exponent2 - this.mantissaBits;
             const pexp = bexp > 0n ? bexp : 0n;
             const nexp = bexp < 0n ? Number(-bexp) : 0;
             const dbin = this.#getMantissaEx() << pexp;
             const dval = base == 10 ? dbin * power5n(nexp) : dbin;
             return this.#toStringSign(plus) + this.#S.#toStringBN(dval, nexp, base);
         }

         toString2F(plus) { return this.#toStringBF(plus, 2); }
         toString10F(plus) { return this.#toStringBF(plus, 10); }

         toString10(plus) {
             if (!this.isPRN())
                 return this.#toStringNPRN(plus);

             const S = this.#S;
             const bits = this.dataBits;
             const rnd0 = this.#round0;
             const toS = S.#toStringBN;

             const bexp = this.exponent2 - this.mantissaBits;
             const pexp = bexp > 0n ? bexp : 0n;
             const nexp = bexp < 0n ? Number(-bexp) : 0;
             const dp5n = power5n(nexp);
             const dval = (this.#getMantissaEx() << pexp) * dp5n;

             const dcol = Math.trunc(LOG10_2 * (BitLength(dp5n << pexp) - 1));
             let dmod = power10n(dcol);
             let dcan = [dval];
             for (;;) {
                 const fcan = dcan.map(v => v - v % dmod);
                 const ccan = fcan.map(v => [v, v + dmod]).flat();
                 const ncan = ccan.filter(v => {
                     const c = new S(bits, toS(v, nexp), rnd0);
                     return (c.finite &&
                             c.exponent == this.exponent &&
                             c.mantissa == this.mantissa);
                 });
                 if (!ncan.length)
                     break;
                 dcan = ncan;
                 dmod *= 10n;
             }
             dcan.sort((a, b) => {
                 const xa = gAbs(a, dval);
                 const xb = gAbs(b, dval);
                 return xa == xb ? 0 : xa < xb ? -1 : 1;
             });
             return this.#toStringSign(plus) + this.#S.#toStringBN(dcan[0], nexp);
         }

         toString16(plus) {
             if (!this.isPRN())
                 return this.#toStringNPRN(plus);
             const mbsz = this.mantissaBits;
             const mshl = -mbsz & 3n;
             const hdec = toString16B(this.mantissa << mshl, mbsz + mshl);
             const hman = `0x${this.exponent ? 1 : 0}.${hdec}`;
             const exp2 = this.exponent2;
             const hexp = (exp2 >= 0 ? '+' : '') + `${exp2}`;
             return this.#toStringSign(plus) + `${hman}p${hexp}`;
         }

         toSepSignExpMan() {
             const sign = this.sign ? 1 : 0;
             const exp = toString16B(this.exponent, this.exponentBits);
             const man = toString16B(this.mantissa, this.mantissaBits);
             return `${sign}:${exp}:${man}`
         }
     }

     class IEEE754Binary16 extends IEEE754Binary { constructor() { super(16, ...arguments); } }
     class IEEE754Binary32 extends IEEE754Binary { constructor() { super(32, ...arguments); } }
     class IEEE754Binary64 extends IEEE754Binary { constructor() { super(64, ...arguments); } }
     class IEEE754Binary128 extends IEEE754Binary { constructor() { super(128, ...arguments); } }

     /*
      *
      */

     const viewOption = {}
     const binaryName = {
         16: '半精度',
         32: '単精度',
         64: '倍精度',
         128: '四倍精度',
     }
     const binaryList = Object.keys(binaryName).map(v => Number(v));
     const viewList = { bin: binaryList }

     const valueName = {
         'dat': '記憶域',
         'sem': '負:指:仮',
         'hex': '16進数',
         'exp': '指数',
         'dec': '非指数',
         'xct': '厳密値',
         'bin': '2進数',
     }
     const valueNameKeys = Object.keys(valueName);

     const optionName = {
         'rnd0': 'ゼロ方向丸め',
         'flip': '表の転置',
     }
     const optionNameKeys = Object.keys(optionName);

     /**/

     let lastInput;

     function toClipboard(text) {
         navigator.clipboard.writeText(text).then(() => {
             if (text.length >= 60)
                 text = text.slice(0, 57) + '⋅⋅⋅';
             tagClipboard.innerText = text;
         }, () => {
             tagClipboard.innerText = 'コピー失敗';
         });
     }
     const tagToClipboard = (tag => toClipboard(tag.innerText));

     function updateViewer() {
         const color_dis = 'lightgray';

         const getTag = (n => document.getElementById(n));
         const setfmt = ((m, n) => {
             const tagTd = getTag(`tagMode_${n}`);
             const tagInp = getTag(`chkbox_${n}`);
             tagInp.checked = viewOption[n];
             tagInp.disabled = !m;
             tagTd.style.backgroundColor = m ? null : color_dis;
         });

         viewOption['fbin'] = binaryList.filter(n => viewOption.bin && viewOption[`bin${n}`]);
         binaryList.forEach(n => setfmt(viewOption.bin, `bin${n}`));

         [['val', valueNameKeys],
          ['opt', optionNameKeys],
         ].forEach(l => {
             const [pfx, keys] = l;
             keys.forEach(k => {
                 const key = `${pfx}${k}`;
                 const tagName = getTag(`chkbox_${key}`);
                 tagName.checked = viewOption[key];
             });
         });
     }

     /**/

     const genCbTag = ((tag, cls, txt) =>
         `<${tag} class="${cls}" onclick="toClipboard('${txt}')">${txt}</${tag}>`
     );
     const genCodeCbTag = ((cls, txt) => genCbTag('code', cls, txt));

     function getValueNameList() {
         return valueNameKeys.map(
             k => viewOption[`val${k}`] ? valueName[k] : null
         ).filter(v=>v);
     }
     function getData(inp) {
         const rnum = new FractionBI(inp);
         const rnd0 = viewOption.optrnd0;
         return {
             inp: inp,
             bin: {
                 list: viewOption.fbin.map(v => {
                     const bin = new IEEE754Binary(v, rnum, rnd0);
                     return {
                         data: bin,
                         tag: [
                             viewOption.valdat ? ['ctext htext', bin.toHexData()] : null,
                             viewOption.valsem ? ['ctext', bin.toSepSignExpMan()] : null,
                             viewOption.valhex ? ['ctext', bin.toString16()] : null,
                             viewOption.valexp ? ['ctext', bin.toExponential()] : null,
                             viewOption.valdec ? ['ctext', bin.toString10()] : null,
                             viewOption.valxct ? ['ctext ftext', bin.toString10F()] : null,
                             viewOption.valbin ? ['ctext ftext', bin.toString2F()] : null,
                         ].filter(v=>v).map(l => genCodeCbTag(l[0], l[1])),
                     }
                 }),
             },
         }
     }

     function genOutputBinBlock1(nlist) {
         const binf = nlist[0].bin; if (!binf.list.length) return '';
         const getBinTag = ((i, b, n) => nlist[i].bin.list[b].tag[n]);
         const cline = ['eline', 'oline'];
         const tagHeader = getValueNameList();
         return [
             '<tr>',
             '<th>形式</th>',
             viewOption.fbin.map(n => `<th>binary${n}</th>`),
             '</tr>',
             nlist.map((s, i) => [
                 '<tr class="inpdata">',
                 '<th style="min-width: 3em;">入力</th>',
                 `<td class="ntext" colspan="${viewOption.fbin.length}">`,
                 genCodeCbTag('ctext large', s.inp),
                 '</td>',
                 '</tr>',
                 tagHeader.map((s, n) => [
                     `<tr class="${cline[n & 1]}">`,
                     `<th class="small">${s}</th>`,
                     viewOption.fbin.map((_, b) => [
                         '<td class="vtop ntext">', getBinTag(i, b, n), '</td>',
                     ]),
                     '</tr>',
             ])]),
         ];
     }

     function genOutputBinBlock2(nlist) {
         const binf = nlist[0].bin; if (!binf.list.length) return '';
         const getBinTag = ((i, b, n) => nlist[i].bin.list[b].tag[n]);
         const cline = ['eline', 'oline'];
         const tagHeader = getValueNameList();
         return [
             '<tr>',
             '<th>形式</th>',
             tagHeader.map(n => `<th>${n}</th>`),
             '</tr>',
             nlist.map((s, i) => [
                 '<tr class="inpdata">',
                 '<th style="min-width: 3em;">入力</th>',
                 `<td class="ntext" colspan="${tagHeader.length}">`,
                 genCodeCbTag('ctext large', s.inp),
                 '</td>',
                 '</tr>',
                 viewOption.fbin.map((w, b) => [
                     `<tr class="${cline[b & 1]}">`,
                     `<th class="small">binary${w}</th>`,
                     tagHeader.map((_, n) => [
                         '<td class="vtop ntext">', getBinTag(i, b, n), '</td>',
                     ]),
                     '</tr>',
             ])]),
         ];
     }

     const input_separator = [
         [...Array(33)].map((_, i) => String.fromCodePoint(i)),
         '!"#$%&\'()*,/:;<=>?@[\\]^`{|}~',
     ].join('');

     function onUpdate(inp) {
         inp = inp ?? tagNumber.innerText;
         const nums = [...input_separator].reduce(
             (p, c) => p.map(s => s.split(c)).flat(), [inp]
         ).filter(v => v != null && v.length);
         if (!nums.length)
             return;
         lastInput = inp;

         const nlist = nums.map(s => getData(s));
         const bintags = (viewOption.optflip ? genOutputBinBlock2 : genOutputBinBlock1)(nlist);

         tagOutput.innerHTML = [
         '<table>', bintags, '</table>', '<p></p>',
         ].flat(8).join('');
     }

     function onChangeViewer(tag) {
         viewOption[tag.id.split('_')[1]] = tag.checked;
         updateViewer();
         onUpdate(lastInput);
     }

     /*
      *
      */

     window.onload = (() => {
         const chkbox = ((n, l) => [
             `<input id="chkbox_${n}" name="chkbox_${n}" type="checkbox"`,
             ` onchange="onChangeViewer(this)">`,
             `<label id="label_${n}" for="chkbox_${n}">${l}</label>`,
         ]);

         const exact = ((n) => new IEEE754Binary64(n).toString16());

         document.body.innerHTML = [
         '<h3>IEEE 754 浮動小数点数 詳細表示</h3>',
         '<div><textarea',
         ' id="tagNumber"', ' cols="72"', ' rows="5"',
         ' placeholder="数値を入力してください"',
         ' oninput="onUpdate(value)">',
         '</textarea></div>',
             /**/
         '<details id="tagSettings"><summary>表示設定</summary>',
         '<table>',
         '<tr>', '<th>データ型</th>',
             Object.entries(binaryName).map(prec => {
                 const [b, l] = prec;
                 return [`<td id="tagMode_bin${b}">`, chkbox(`bin${b}`, l), `(${b})</td>`];
             }),
             '</tr>',
             '</table>',
             '<table style="margin-top: 2px;">',
             '<tr>', '<th>表示項目</th>',
             Object.entries(valueName).map(v => [
                 `<td id="tagView_val${v[0]}">`, chkbox(`val${v[0]}`, v[1]), '</td>'
             ]),
             '</tr>',
             '</table>',
             '<table style="margin-top: 2px;">',
             '<tr>', '<th>その他</th>',
             Object.entries(optionName).map(v => [
                 `<td id="tagOption_opt${v[0]}">`, chkbox(`opt${v[0]}`, v[1]), '</td>'
             ]),
             '</table>',
             '</details>',
             /**/
             '<div>&nbsp;</div>',
             '<div class="xsmall">クリップボード:<code id="tagClipboard">(数値をクリック)</code></div>',
             '<div>&nbsp;</div>',
             '<div id="tagOutput"></div>',
             '<div>&nbsp;</div>',
             '<table>',
             '<tr><th colspan="4">定数テスト(binary64)</th></tr>',
             [['PI', 'LN2', 'LOG2E', 'SQRT1_2'],
              ['E', 'LN10', 'LOG10E', 'SQRT2'],
             ].map(l => [
                 '<tr>',
                 l.map(n => [
                     '<td style="padding: 2px;">',
                     `<button onclick="onUpdate('${exact(Math[n])}')">Math.${n}</button>`,
                     '</td>',
                 ]),
                 '</tr>',
             ]),
             '</table>',
             '<div>&nbsp;</div>',
             '<table>',
             '<tr class="small"><th colspan="2">説明</th></tr>',
             '<tr class="small eline"><th>入力</th><td>改行などの区切りで複数値に対応</td></tr>',
             '<tr class="small"><th>表示項目</th><th>浮動小数点数に対する内容</th></tr>',
             '<tr class="small eline"><th>記憶域</th><td>メモリ上のデータ</td></tr>',
             '<tr class="small oline"><th>負:指:仮</th><td>符号ビット、指数部(16進)、仮数部(16進)の値</td></tr>',
             '<tr class="small eline"><th>16進数</th><td>指数形式16進数(厳密値)</td></tr>',
             '<tr class="small oline"><th>指数</th><td>指数形式10進数(近似値)</td></tr>',
             '<tr class="small eline"><th>非指数</th><td>10進数(近似値)</td></tr>',
             '<tr class="small oline"><th>厳密値</th><td>10進数(厳密値)</td></tr>',
             '<tr class="small eline"><th>2進数</th><td>2進数(厳密値) : 前置 \'0b\' は省略</td></tr>',
             '</table>',
         ].flat(9).join('');

         /*
          * URLの引数
          *
          * on=<type> または off=<type> で表示を制御
          *
          * <type>:
          *   setting: 表示設定
          *
          *   bin16: 2進数半精度
          *   bin32: 2進数単精度
          *   bin64: 2進数倍精度
          *   bin128: 2進数四倍精度
          *
          *   valdat: 記憶域
          *   valsem: 負:指:仮
          *   valhex: 16進
          *   valexp: 指数
          *   valdec: 非指数
          *   valxct: 厳密値
          *   valbin: 2進数
          *
          *   optrnd0: ゼロ方向丸め
          *   optflip: 表の転置
          */

         const set_flag = ((f, v) => {
             const p = v.slice(0, 3);
             if (viewList[p]) {
                 if (f)
                     viewOption[p] = f;
                 viewOption[v] = f;
                 return;
             }

             const s = v.slice(3);
             if (p == 'val') {
                 if (valueName[s])
                     viewOption[v] = f;
                 return;
             }
             if (p == 'opt') {
                 if (optionName[s])
                     viewOption[v] = f;
                 return;
             }
             if (v == 'setting') {
                 tagSettings.open = f;
                 return;
             }

             // ...
         });
         const set_flags = ((f, l) => l.forEach(v => set_flag(f, v)));

         /**/

         const url = new URL(window.location);
         const search = url.searchParams;

         const get_arglist = (l => l.map(n => search.getAll(n).map(v => v.split(','))).flat(5));
         const args_on = get_arglist(['on', 's']);
         const args_off = get_arglist(['off', 'u']);
         const args_inp = search.getAll('n').join('\n');

         set_flags(true, ['bin32', 'bin64']);
         set_flags(true, valueNameKeys.map(k => `val${k}`));

         set_flags(true, args_on);
         set_flags(false, args_off);

         updateViewer();
         onUpdate(args_inp.length ? args_inp : `${exact(Math.PI)}`);
     });

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

Python コマンドライン版

Python ソースコード(長いので折りたたみ)
sample.py
#!/usr/bin/env python3

import math


class IEEE754Binary:
    """IEEE 754 - Binary 形式"""

    class _Parameter:
        """符号部、指数部、仮数部の情報"""

        def __init__(self, exponent_bits: int, mantissa_bits: int):
            self.mantissa_position = 0
            self.mantissa_bits = mantissa_bits
            self.mantissa_int = 1 << mantissa_bits
            self.mantissa_mask = self.mantissa_int - 1

            self.exponent_position = mantissa_bits
            self.exponent_bits = exponent_bits
            self.exponent_mask = (1 << exponent_bits) - 1
            self.exponent_bias = self.exponent_mask >> 1

            self.sign_position = self.exponent_position + exponent_bits
            self.sign_bit = 1 << self.sign_position

    # ----------

    _BINARY_TABLE = {
        16: _Parameter(5, 10),
        32: _Parameter(8, 23),
        64: _Parameter(11, 52),
        128: _Parameter(15, 112),
    }

    # ----------

    _BASE2_TABLE = {f'{n}': n for n in range(2)}
    _BASE8_TABLE = {f'{n}': n for n in range(8)}
    _BASE10_TABLE = {f'{n}': n for n in range(10)}
    _BASE16_TABLE = {f'{n:x}': n for n in range(16)}

    _BASE_TABLE = {
        'b': (2, _BASE2_TABLE),
        'o': (8, _BASE8_TABLE),
        'x': (16, _BASE16_TABLE),
    }

    # ----------

    def __init__(self, data_bits: int, value: any = None, round_toward_zero: bool = None):
        self._round_toward_zero = round_toward_zero

        self._data_bits = data_bits
        self._parameter = IEEE754Binary._BINARY_TABLE[self._data_bits]

        self._binary = None

        self._nan = None
        self._finite = None

        self._sign = None
        self._exponent = None
        self._mantissa = None

        self._numerator = None
        self._denominator = None

        if value is None:
            self._set_zero(False)
        elif isinstance(value, int):
            self._from_int(value)
        elif isinstance(value, float):
            self._from_float(value)
        elif isinstance(value, str):
            self._from_string(value)
        elif isinstance(value, IEEE754Binary):
            self._from_binary(value)
        else:
            raise TypeError(value)

    def __repr__(self) -> str:
        """10進数文字列を返す"""
        return self._str_decimal()

    # ----------

    @property
    def round_toward_zero(self) -> bool:
        """ゼロ方向丸めの場合は True"""
        return self._round_toward_zero

    @property
    def data_bits(self) -> int:
        """浮動小数点データのビット数"""
        return self._data_bits

    @property
    def binary(self) -> int:
        """記憶域用のデータ"""
        return self._binary

    @property
    def nan(self) -> bool:
        """非数の場合は True"""
        return self._nan

    @property
    def finite(self) -> bool:
        """有限値の場合は True"""
        return self._finite

    @property
    def sign(self) -> (bool, None):
        """負の場合は True"""
        return self._sign

    @property
    def sign_position(self) -> int:
        """符号のビット位置"""
        return self._parameter.sign_position

    @property
    def exponent(self) -> int:
        """指数部のデータ"""
        return self._exponent

    @property
    def exponent_position(self) -> int:
        """指数部のビット位置"""
        return self._parameter.exponent_position

    @property
    def exponent_bias(self) -> int:
        """指数部のバイアス値"""
        return self._parameter.exponent_bias

    @property
    def exponent_bits(self) -> int:
        """指数部のビット数"""
        return self._parameter.exponent_bits

    @property
    def mantissa(self) -> int:
        """仮数部のデータ"""
        return self._mantissa

    @property
    def mantissa_bits(self) -> int:
        """仮数部のビット数"""
        return self._parameter.mantissa_bits

    @property
    def numerator(self) -> (int, None):
        """分数表現での分子"""
        return self._numerator

    @property
    def denominator(self) -> (int, None):
        """分数表現での分母"""
        return self._denominator

    # ----------

    def _set_binary(self) -> 'IEEE754Binary':
        param = self._parameter
        sign = param.sign_bit if self.sign else 0
        exp = self._exponent << param.exponent_position
        self._binary = sign | exp | self._mantissa
        return self

    def _set_nan(self, sign: bool) -> 'IEEE754Binary':
        param = self._parameter
        self._nan = True
        self._finite = False
        self._sign = sign
        self._exponent = param.exponent_mask
        self._mantissa = param.mantissa_int >> 1
        self._numerator = None
        self._denominator = None
        return self._set_binary()

    def _set_inf(self, sign: bool) -> 'IEEE754Binary':
        self._nan = False
        self._finite = False
        self._sign = sign
        self._exponent = self._parameter.exponent_mask
        self._mantissa = 0
        self._numerator = None
        self._denominator = None
        return self._set_binary()

    def _set_zero(self, sign: bool) -> 'IEEE754Binary':
        self._nan = False
        self._finite = True
        self._sign = sign
        self._exponent = 0
        self._mantissa = 0
        self._numerator = 0
        self._denominator = 1
        return self._set_binary()

    def _set_finite(self, sign: bool, numerator: int, denominator: int) -> 'IEEE754Binary':
        if not denominator:
            return (self._set_inf if numerator else self._set_nan)(sign)
        if not numerator:
            return self._set_zero(sign)

        self._nan = False
        self._finite = True
        self._sign = sign

        param = self._parameter

        bmask = numerator | denominator
        shift = (bmask & -bmask).bit_length() - 1
        numerator >>= shift
        denominator >>= shift
        while True:
            ndiv, nmod = divmod(numerator, 5)
            ddiv, dmod = divmod(denominator, 5)
            if nmod or dmod:
                break
            numerator = ndiv
            denominator = ddiv
        self._numerator = numerator
        self._denominator = denominator

        fnum = numerator
        fden = denominator

        exp = fnum.bit_length() - fden.bit_length()
        if exp >= 0:
            fden <<= exp
        else:
            fnum <<= -exp
        if fnum < fden:
            fnum <<= 1
            exp -= 1

        exp += param.exponent_bias
        if exp <= 0:
            fden <<= 1 - exp
            exp = 0

        xnum = fnum << param.mantissa_bits
        xdiv = xnum // fden
        xrem = xnum % fden

        xcmp = (xrem << 1) - fden
        xrnd = (1 if not self._round_toward_zero and
                ((xcmp > 0) or ((xcmp == 0) and (xdiv & 1))) else 0)

        man = xdiv + xrnd
        mshift = int(exp > 0)
        if man >= (param.mantissa_int << mshift):
            man >>= mshift
            exp += 1
        if exp < param.exponent_mask:
            self._exponent = exp
            self._mantissa = man & param.mantissa_mask
        else:
            self._finite = False
            self._exponent = param.exponent_mask
            self._mantissa = 0
        return self._set_binary()

    def setfrac(self, sign: bool, numerator: int, denominator: int) -> 'IEEE754Binary':
        """分数で値を設定する"""
        return self._set_finite(sign, numerator, denominator)

    @staticmethod
    def fromfrac(data_bits: int, round_toward_zero: bool,
                 sign: bool, numerator: int, denominator: int) -> 'IEEE754Binary':
        """分数から IEEE754Binary を作る"""
        fpval = IEEE754Binary(data_bits, None, round_toward_zero)
        return fpval.setfrac(sign, numerator, denominator)

    # ----------

    def _from_int(self, rhs: int) -> 'IEEE754Binary':
        return self._set_finite(rhs < 0, abs(rhs), 1)

    def _from_float(self, rhs: float) -> 'IEEE754Binary':
        sign = math.copysign(1.0, rhs) < 0
        if not math.isfinite(rhs):
            return (self._set_nan if math.isnan(rhs) else self._set_inf)(sign)
        if not rhs:
            return self._set_zero(sign)
        man, exp = math.frexp(rhs)
        iman = int(man * (1 << 53))
        iexp = exp - 53
        bnum = iman << max(0, iexp)
        bden = 1 << max(0, -iexp)
        return self._set_finite(sign, bnum, bden)

    def _from_binary(self, rhs: 'IEEE754Binary') -> 'IEEE754Binary':
        self._round_toward_zero = rhs.round_toward_zero
        self._data_bits = rhs.data_bits
        self._parameter = IEEE754Binary._BINARY_TABLE[self._data_bits]
        self._binary = rhs.binary
        self._nan = rhs.nan
        self._finite = rhs.finite
        self._sign = rhs.sign
        self._exponent = rhs.exponent
        self._mantissa = rhs.mantissa
        self._numerator = rhs.numerator
        self._denominator = rhs.denominator
        return self

    def _from_string(self, text: str) -> 'IEEE754Binary':
        text = text.strip().lower()

        fsign = False
        fnum = 0
        fden = 1

        tpos = 0
        if tpos >= len(text):
            return self._set_nan(fsign)
        tch = text[tpos]
        if tch in ('-+'):
            fsign = tch == '-'
            tpos += 1
            if tpos >= len(text):
                return self._set_nan(fsign)

        tch = text[tpos:]
        if tch == 'nan':
            return self._set_nan(fsign)
        if tch in ('inf', 'infinity'):
            return self._set_inf(fsign)

        dtab = self._BASE10_TABLE
        btab = dtab
        base = 10

        if tpos >= len(text):
            return self._set_nan(fsign)
        tch = text[tpos]
        if tch == '0':
            tpos += 1
            if tpos >= len(text):
                return self._set_finite(fsign, fnum, fden)
            tch = text[tpos]
            bmap = self._BASE_TABLE.get(tch)
            if bmap:
                base, btab = bmap
                tpos += 1
                if tpos >= len(text):
                    return self._set_nan(fsign)
                tch = text[tpos]

        dot = False
        while True:
            cnum = btab.get(tch)
            if cnum is not None:
                fnum = fnum * base + cnum
                if dot:
                    fden *= base
            elif tch not in ('_,'):
                if tch != '.':
                    break
                if dot:
                    return self._set_nan(fsign)
                dot = True
            tpos += 1
            if tpos >= len(text):
                return self._set_finite(fsign, fnum, fden)
            tch = text[tpos]

        expm = base
        if tch not in ('ep'):
            return self._set_nan(fsign)
        if tch == 'p':
            if expm == 10:
                return self._set_nan(fsign)
            expm = 2
        tpos += 1
        if tpos >= len(text):
            return self._set_nan(fsign)
        tch = text[tpos]

        esign = False
        if tch in ('-+'):
            esign = tch == '-'
            tpos += 1
            if tpos >= len(text):
                return self._set_nan(fsign)
            tch = text[tpos]

        xnum = 0
        while True:
            cnum = dtab.get(tch)
            if cnum is None:
                return self._set_nan(fsign)
            xnum = xnum * 10 + cnum
            tpos += 1
            if tpos >= len(text):
                break
            tch = text[tpos]
        if xnum >= 10000000:
            return (self._set_zero if esign else self._set_inf)(fsign)

        expv = 1
        while xnum:
            if xnum & 1:
                expv *= expm
            expm *= expm
            xnum >>= 1
        if esign:
            fden *= expv
        else:
            fnum *= expv
        return self._set_finite(fsign, fnum, fden)

    # ----------

    def _is_prn(self) -> bool:
        return not self._finite or not (self._exponent or self._mantissa)

    def _str_sign(self, plus: bool = None) -> str:
        return '-' if self._sign else '+' if plus else ''

    def _str_nan(self) -> str:
        return 'nan'

    def _str_inf(self, plus: bool = None) -> str:
        return self._str_sign(plus) + 'inf'

    def _str_zero(self, plus: bool = None) -> str:
        return self._str_sign(plus) + '0'

    def _str_prn(self, plus: bool = None) -> str:
        return (self._str_nan() if self._nan else
                (self._str_zero if self._finite else self._str_inf)(plus))

    def _str_decimal(self, plus: bool = None, efmt: bool = None, exact: bool = None) -> str:
        if self._is_prn():
            return self._str_prn(plus)

        param = self._parameter
        dexp = self._exponent
        dman = self._mantissa

        bexp = max(1, dexp) - param.exponent_bias - param.mantissa_bits
        pexp = max(0, bexp)
        nexp = max(0, -bexp)
        bman = dman | (param.mantissa_int if dexp else 0)
        dp5n = pow(5, nexp)
        fnum = (bman << pexp) * dp5n
        fden = dp5n << nexp

        log10_2 = 0.3010299956639812
        dmod = pow(10, int(log10_2 * ((dp5n << pexp).bit_length() - 1)))

        _new = self.fromfrac
        bits = self._data_bits
        frtz = self._round_toward_zero

        def check(value):
            chk = _new(bits, frtz, False, value, fden)
            return chk.finite and chk.exponent == dexp and chk.mantissa == dman

        dcan = [fnum]
        while not exact:
            fcan = [v - v % dmod for v in dcan]
            ccan = [v + dmod for v in fcan]
            ncan = list(filter(check, fcan + ccan))
            if not ncan:
                break
            dcan = ncan
            dmod *= 10
        fnum = sorted(dcan, key=lambda v: abs(v - fnum))[0]
        snum = self._format_decimal(fnum, nexp)
        if efmt:
            snum = self._str_dec_exp(snum)
        return f'{self._str_sign(plus)}{snum}'

    def _str_hexadecimal(self, plus: bool = None) -> str:
        if self._is_prn():
            return self._str_prn(plus)

        param = self._parameter
        dexp = self._exponent
        dman = self._mantissa
        mbsz = param.mantissa_bits
        mshl = -mbsz & 3
        hdec = self._format_hexadecimal(dman << mshl, mbsz + mshl)
        hman = f'0x{int(bool(dexp))}.{hdec}'
        exp2 = max(1, dexp) - param.exponent_bias
        hexp = f'+{exp2}' if exp2 >= 0 else f'{exp2}'
        return f'{self._str_sign(plus)}{hman}p{hexp}'

    @staticmethod
    def _format_decimal(dval: int, nexp: int) -> str:
        dstr = str(dval)
        if not nexp:
            return dstr
        mstr = '0' * max(0, nexp - len(dstr)) + dstr
        mint, mdec = mstr[:-nexp], mstr[-nexp:].rstrip('0')
        return ((mint if mint else '0') + f'.{mdec}').rstrip('.')

    @staticmethod
    def _str_dec_exp(nstr: str) -> str:
        sint, sdec = (nstr.split('.') + [''])[:2]
        if sint == '0':
            edec = len(sdec)
            sdec = sdec.lstrip('0')
            snum = f'{sdec[:1]}.{sdec[1:]}'.rstrip('.')
            return f'{snum}e-{edec - len(sdec) + 1}'

        eint = len(sint)
        snum = (sint + sdec).rstrip('0')
        snum = f'{snum[:1]}.{snum[1:]}'.rstrip('.')
        return f'{snum}e+{eint - 1}'

    @staticmethod
    def _format_hexadecimal(value: int, bits: int) -> str:
        cnt = max(1, (bits + 3) >> 2)
        return ('0' * cnt + f'{value:x}')[-cnt:]

    # ----------

    def data(self):
        """記憶域用の16進データ文字列を返す"""
        return '0x' + self._format_hexadecimal(self._binary, self._data_bits)

    def sep(self):
        """負:指:仮 分離形式を返す"""
        param = self._parameter
        sign = int(self._sign)
        exp = self._format_hexadecimal(self._exponent, param.exponent_bits)
        man = self._format_hexadecimal(self._mantissa, param.mantissa_bits)
        return f'{sign}:{exp}:{man}'

    def dec(self, plus: bool = None, efmt: bool = None) -> str:
        """10進文字列を返す"""
        return self._str_decimal(plus=plus, efmt=efmt)

    def full(self, plus: bool = None, efmt: bool = None) -> str:
        """10進全桁の文字列を返す"""
        return self._str_decimal(plus=plus, efmt=efmt, exact=True)

    def hex(self, plus: bool = None) -> str:
        """指数形式16進文字列を返す"""
        return self._str_hexadecimal(plus=plus)


class IEEE754Binary16(IEEE754Binary):
    def __init__(self, value: any = None, round_toward_zero: bool = None):
        super().__init__(16, value, round_toward_zero)


class IEEE754Binary32(IEEE754Binary):
    def __init__(self, value: any = None, round_toward_zero: bool = None):
        super().__init__(32, value, round_toward_zero)


class IEEE754Binary64(IEEE754Binary):
    def __init__(self, value: any = None, round_toward_zero: bool = None):
        super().__init__(64, value, round_toward_zero)


class IEEE754Binary128(IEEE754Binary):
    def __init__(self, value: any = None, round_toward_zero: bool = None):
        super().__init__(128, value, round_toward_zero)


if __name__ == '__main__':
    import argparse
    import sys

    def main():
        parser = argparse.ArgumentParser()
        # parser.add_argument('-v', '--verbose', action='store_true')
        parser.add_argument('-H', '--binary16', action='store_true', help='半精度(binary16)を使用する')
        parser.add_argument('-S', '--binary32', action='store_true', help='単精度(binary32)を使用する')
        parser.add_argument('-D', '--binary64', action='store_true', help='倍精度(binary64)を使用する')
        parser.add_argument('-Q', '--binary128', action='store_true', help='四倍精度(binary128)を使用する')
        parser.add_argument('-s', '--storage', action='store_true', help='記憶域用データを表示する')
        parser.add_argument('-p', '--parameter', action='store_true', help='負:指:仮 分離形式を表示する')
        parser.add_argument('-x', '--hex', action='store_true', help='16進数を表示する')
        parser.add_argument('-e', '--exp', action='store_true', help='指数形式10進数を表示する')
        parser.add_argument('-d', '--dec', action='store_true', help='10進数を表示する')
        parser.add_argument('-f', '--full', action='store_true', help='厳密値を表示する')
        parser.add_argument('-0', '--roundtowardzero', action='store_true', help='ゼロ方向丸めを使用する')
        parser.add_argument('numbers', metavar='N', nargs='+')
        args = parser.parse_args()

        binary_types = tuple(filter(None, [
            ('binary16', IEEE754Binary16) if args.binary16 else None,
            ('binary32', IEEE754Binary32) if args.binary32 else None,
            ('binary64', IEEE754Binary64) if args.binary64 else None,
            ('binary128', IEEE754Binary128) if args.binary128 else None,
        ]))
        if not binary_types:
            print('オプション -H, -S, -D, -Q から1つ以上指定してください')
            parser.print_help()
            sys.exit(2)

        sep = '-' * 32
        for num in args.numbers:
            print('\n'.join([sep, f'入力文字列: "{num}"', sep]))
            for bname, btype in binary_types:
                fpval = btype(num, round_toward_zero=args.roundtowardzero)
                [print(line) for line in filter(lambda s: s is not None, [
                    f'{bname}',
                    f'  記憶域: {fpval.data()}' if args.storage else None,
                    f'  分離  : {fpval.sep()}' if args.parameter else None,
                    f'  16進  : {fpval.hex()}' if args.hex else None,
                    f'  指数  : {fpval.dec(efmt=True)}' if args.exp else None,
                    f'  非指数: {fpval.dec()}' if args.dec else None,
                    f'  厳密値: {fpval.full()}' if args.full else None,
                    '',
                ])]

    sys.exit(main())
実行結果(ゼロ方向丸め)
% ./sample.py -HSD -spxedfb -0 0.001
--------------------------------
入力文字列: "0.001"
--------------------------------
binary16
  記憶域: 0x1418
  分離  : 0:05:018
  16進  : 0x1.060p-10
  指数  : 1e-3
  非指数: 0.001
  厳密値: 0.00099945068359375
  2進数 : 0.00000000010000011

binary32
  記憶域: 0x3a83126e
  分離  : 0:75:03126e
  16進  : 0x1.0624dcp-10
  指数  : 1e-3
  非指数: 0.001
  厳密値: 0.00099999993108212947845458984375
  2進数 : 0.00000000010000011000100100110111

binary64
  記憶域: 0x3f50624dd2f1a9fb
  分離  : 0:3f5:0624dd2f1a9fb
  16進  : 0x1.0624dd2f1a9fbp-10
  指数  : 1e-3
  非指数: 0.001
  厳密値: 0.00099999999999999980397624721462079833145253360271453857421875
  2進数 : 0.00000000010000011000100100110111010010111100011010100111111011
実行結果(近傍丸め)
% ./sample.py -HSD -spxedfb 0.001
--------------------------------
入力文字列: "0.001"
--------------------------------
binary16
  記憶域: 0x1419
  分離  : 0:05:019
  16進  : 0x1.064p-10
  指数  : 1e-3
  非指数: 0.001
  厳密値: 0.00100040435791015625
  2進数 : 0.00000000010000011001

binary32
  記憶域: 0x3a83126f
  分離  : 0:75:03126f
  16進  : 0x1.0624dep-10
  指数  : 1e-3
  非指数: 0.001
  厳密値: 0.001000000047497451305389404296875
  2進数 : 0.000000000100000110001001001101111

binary64
  記憶域: 0x3f50624dd2f1a9fc
  分離  : 0:3f5:0624dd2f1a9fc
  16進  : 0x1.0624dd2f1a9fcp-10
  指数  : 1e-3
  非指数: 0.001
  厳密値: 0.001000000000000000020816681711721685132943093776702880859375
  2進数 : 0.000000000100000110001001001101110100101111000110101001111111
0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?