最終更新日時(UTC): 2024年07月10日 07時47分57秒
Akira Takahashi が更新

履歴 編集

# 16進浮動小数点数リテラル [P0245R1](C++17)

このページはC++17に採用された言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

## 概要

2を底とする、指数表記の十六進浮動小数点数リテラルがサポートされた。

## 仕様

    十六進プレフィックス 仮数部 指数部 サフィックス

1. 十六進プレフィックス: `0[xX]`
   - `0x` または `0X`
2. 仮数部: `([0-9a-fA-F]*\.[0-9a-fA-F]+|[0-9a-fA-F]+\.?)`
   - 十六進整数部`.`十六進小数部
   - 十六進整数部`.`
   - `.`十六進小数部
   - 十六進整数
3. 指数部 (底2): `[pP][+-]?[0-9]+`
   1. `p` または `P`
   2. 符号 `+` または `-` (任意)
   3. 十進数
4. サフィックス: `[flFL]?`
   - `f`, `F`, `l`, `L` のいずれか (任意)
   - サフィックスを省略した場合は`double`型、`f`もしくは`F`を指定した場合は`float`型、`l`もしくは`L`を指定した場合は`long double`型となる

`0xSIGpEXP` は $(\text{SIG})_{16} \times 2^{(\text{EXP})_{10}}$ である。 たとえば `0xABCp-3` は十進数で $(10 \times 16^2 + 11 \times 16 + 12) \times 2^{-3} = 343.5$ である。

十六進浮動小数点数リテラルには 桁区切り文字を使用できる。

十六進表記で浮動小数点数を出力するには、 `std::ostream` では `std::hexfloat`、 `std::printf` では `%a`/`%A` を用いる。

`std::strtod` は十六進表記で浮動小数点数の入力を受け取る (が実際には機能しない; 詳細は備考参照)。

## 例

    #include <iostream>

    int main()
    {
      std::cout << 0xABCp-3f << '\n';
      double dbl_min = 0x1.0p-1'022; // 1 * 2^-1022 (double の正の正規化数の最小値)
      std::cout << dbl_min << '\t' << std::hexfloat << dbl_min << '\n';
      return 0;
    }

### 出力

    343.5
    2.22507e-308    0x1p-1022

## この機能が必要になった背景・経緯

十六進リテラルによってある浮動小数点数を正確に表現することができるようになった。

## 備考

### C

C99 で十六進浮動小数リテラルが採用された。

### iostream の問題

`std::strtod` は `pP` を認識しないため、十六進表記で浮動小数点数を受け取って適切に変換することができない (LWG issue 2381)。

## 参照

- P0245R0 Hexadecimal floating literals for C++
- P0245R1 Hexadecimal floating literals for C++