real および float データ型におけるアンダーフロー時の動作

 

 

神谷 雅紀
Escalation Engineer

 

real および float 浮動小数点データ型においてアンダーフローが発生した場合、エラーは発生しません。0 が設定されます。

 

各データ型で格納可能な数値範囲は以下の通りです。

 

データ型 格納可能な数値範囲
real - 3.40E+38 ~ -1.18E-38、0、および 1.18E-38 ~ 3.40E+38
float - 1.79E+308 ~ -2.23E-308、0、および 2.23E-308 ~ 1.79E+308

 

 

以下は、その動作を確認することのできる簡単なサンプルです。

 

float 型に格納可能な最小値よりも小さな 2.23E-309 を格納しようとすると、結果は 0 になります。それを示す警告も返されます。

 

declare @r float
set @f = 2.23E-309
select @f as 'float'

警告: 浮動小数点値 '2.23E-309' は小さすぎます。この値は 0 と見なされます。
float
----------------------
0

 

real が格納可能な数値よりも小さな数値 1.18E-39 を格納しようとすると、結果は 0 になります。

 

declare @r real
set @r = 1.18E-39
select @r as 'real'

real
-------------
0

1.18E-39 を格納可能な float に一旦入れた後に、それを real にコピーしても 0 になります。

 

declare @r real, @f float
set @f = 1.18E-39
set @r = @f
select @f as 'float', @r as 'real'

 

float                  real
---------------------- -------------
1.18E-39               0

計算の結果としてアンダーフローが発生した場合も 0 になります。

declare @r real
set @r = 1.18E-38
select @r as '1.18E-38'
set @r = @r * @r
select @r as '1.18E-38 * 1.18E-38'

 

1.18E-38
-------------
1.18E-38

 

1.18E-38 * 1.18E-38
-------------------
0

 

追加情報

SQL Server 2012 では浮動小数点型パラメータを使用した RPC (* 1) において、real 型の範囲を超えた値を渡すと以下のエラーが発生するという問題がありました。

エラーメッセージ

着信の表形式のデータ ストリーム (TDS) リモート プロシージャ コール (RPC) のプロトコル ストリームが正しくありません。パラメーター X ("XXX"): 指定した値はデータ型 real の有効なインスタンスではありません。ソース データに無効な値があるかどうかを確認してください。たとえば、小数点以下桁数が有効桁数より大きい数値型のデータは無効です。

この問題は、以前のバージョンでは許可されていなかった非正規化浮動小数点数 (denormalized float/real) が、現在のバージョンでは許可されているものの、一部不要なチェックが残っていたために発生していました。

この問題は SQL Server 2014 では修正されています。この修正により、浮動小数点型パラメーターの値として real 型の範囲を超えた値を渡していたアプリケーションでは、SQL Server 2012 ではエラーになっていたものが、SQL Server 2014 では値 0 として扱われるようになります。

 

(*1) RPC: Remote Procedure Call の略。クライアントアプリケーションが SQL Server に対して要求を送信する方法のひとつ。バッチ (Batch) もしくは Language と呼ばれる方法が SQL Server に対して T-SQL 文字列を渡すのに対して、RPC は呼び出すストアドプロシージャの名前もしくは番号と各パラメーターのデータ型および値を渡す。SQL トレースや拡張イベントのイベント名 “RPC:Completed” などの “RPC” はこれ。