● 型
FLOATEX値と FLOATEX_VALUE 共用体
floatex.h に、FLOATEX_VALUE 共用体が定義されています。
FLOATEX_VALUE 共用体.
typedef union {
FLOATEX fex_val;
#ifdef FEX_LONG_DOUBLE_SUPPORT
long double ld_val;
#endif
struct {
UINT64 mantissa;
unsigned int exp : 15;
unsigned int sign : 1;
} bits;
} FLOATEX_VALUE,*PFLOATEX_VALUE;
FLOATEX 型と long double 型を変換する時や、FLOATEX 型を拡張倍精度浮動小数点型のフォーマットに分解する時等に使用します。
- メンバ fex_val
FLOATEX 型の変数です。
- メンバ ld_val
このメンバを使用する時は、FEX_LONG_DOUBLE_SUPPORT を定義してください。コンパイラが 80 bit 精度の long double 型に対応している事が必要条件です。
このメンバは、FLOATEX 型と long double 型を変換する時に使用します。80 bit 精度の long double 型でも、コンパイラによってはサイズが異なる事があります。その場合、この共用体に差を吸収させます。
- 構造体メンバ bits
- メンバ mantissa
FLOATEX 型の仮数部です。MSB は整数部で、1 を表します(J ビット)。その下は小数部で、LSB に向かって 2-1 、2-2 、2-3 … 2-63 となっています。
仮数部全体としては 1 ≦ mantissa < 2 となります。ただし、デノーマル値の場合は 0 < mantissa < 1 となり、±0 の場合は mantissa = 0 、±∞の場合は mantissa = 0x8000000000000000 となります。
- メンバ exp
FLOATEX型の指数部です。15 ビットの符号無し整数値で、底は 2 です。
値にはバイアスが加わっており、exp−16383 が実際の指数となります。ただし、デノーマル値と±0 の場合は exp = 0 、±∞と NaN の場合は exp = 0x7fff となります。
- メンバsign
FLOATEX型全体に対する符号です。0 は正、1 は負を表します。
符号は特殊数(デノーマル、∞、NaN)にも付きます。ゼロにも符号が付きますが、値の比較操作では、ゼロの符号は無視されます。
デノーマル数
値が 2-16382 よりも小さい場合は、15 ビットのバイアス付き指数では表現する事ができないので、仮数部をビット単位で右シフトして、全体を真の値に近付けます(指数部に入り切らない分を、仮数部を小さくする事で持たせる)。この値は「デノーマル数」と呼ばれます。ビットパターンは指数部が 0 で、仮数部の MSB が 0 となります(MSB が 1 の場合は「擬似デノーマル数」)。
デノーマル数では、仮数部の上位側にゼロを挿入するので、有効桁数が減り、精度が落ちます。
デノーマル数は、無限大や NaN と同じ特殊数という扱いになります。FPU からデノーマル化された結果が返された場合は、アンダーフロー例外が発生した事を意味します。また、デノーマル数を演算しようとした場合は、デノーマライズド・オペランド例外が発生します。
非数(NaN:Not a Number)
- マスクされた無効操作例外が発生した場合、多くの FPU 演算命令は クワイエット型 NaN(QNaN)を返します。これは、指数部が 0x7fff で、仮数部の上位 2 ビットが 11b のデータです。QNaN が入力に使用された場合、大部分の FPU 命令は例外を発生しません。
- シグナル型 NaN(SNaN)は、指数部が 0x7fff 、仮数部の上位 2 ビットが 10b の NaN で、入力に使用された場合は、マスクされていなければ無効操作例外を発生します。FPU が演算結果として SNaN を返す事はありません。
仮数部の LSB から 61 bit 目までは、任意の目的で使用する事ができます。
(関連:「例外処理」 、floatex_qnan 、floatex_snan)
テスト. QNaN の各要素を表示する
#include <stdio.h>
#include "floatex.h"
void main(void)
{
FLOATEX_VALUE a;
unsigned int oldcw;
oldcw = floatex_storecw();
floatex_loadcw(FEX_MCW_EM | FEX_PC_64 | FEX_RC_NEAR);
floatex_qnan(1,a.fex_val);
floatex_nabs(a.fex_val);
printf(" 符号:%d\n",a.bits.sign);
printf("指数部:%x\n",a.bits.exp);
printf("仮数部:%I64x\n",a.bits.mantissa);
floatex_loadcw(oldcw);
}
結果.
符号:1
指数部:7fff
仮数部:c000000000000001