この問題は、longdoubleからdoubleへの変換が原因ではありません。sin
数学ライブラリのルーチンが不正確であることが原因である可能性があります。
命令は、fsin
その範囲内のオペランドに対して1 ULP(long double形式)内の結果を生成するように指定されています(Intel 64およびIA-32アーキテクチャソフトウェア開発者マニュアル、2011年10月、第1巻、8.3.10による)。 to-nearestモード。Intel Core i7では、fsin
質問者の値の-5.07121364272633190495298549649305641651153564453125または-0x1.448ec3aaa278dp+2は、0xe.fb206c69b0ba402p-4を生成します。この16進数から、最後の11ビットが100 0000 0010であることが簡単にわかります。これらは、longdoubleから変換するときに丸められるビットです。100 0000 0000より大きい場合、数値は切り上げられます。彼らはより大きいです。したがって、このlong double値をdoubleに変換した結果は、0xe.fb206c69b0ba8p-4になります。これは、0x1.df640d8d36175p-1および0.93631021832247418590355891865328885614871978759765625に等しくなります。また、結果が1 ULP低い場合でも、最後の11ビットは100 0000 0000より大きく、切り上げられることに注意してください。したがって、この結果は、上記のドキュメントに準拠するIntelCPUでは変化しないはずです。
sin
これを、正しく丸められた結果を生成する理想的なルーチンを使用して、倍精度の正弦を直接計算することと比較してください。値の正弦は、約0.93631021832247413051857150785044253634581268961333520518023697738674775240815140702992025520721336793516756640679315765619707343171517531053811196321335899848286682535203710849065933755262347468763562(Maple 10で計算)です。これに最も近いdoubleは0x1.df640d8d36175p-1です。fsin
これは、結果をdoubleに変換して得られた値と同じです。
したがって、不一致はlongdoubleからdoubleへの変換によって引き起こされるものではありません。long doubleのfsin
結果をdoubleに変換すると、理想的な倍精度sin
ルーチンとまったく同じ結果が得られます。
sin
質問者のVisualStudioパッケージで使用されるルーチンの精度に関する仕様はありません。商用ライブラリでは、1つのULPまたは複数のULPのエラーを許可するのが一般的です。正弦が倍精度値が丸められるポイントにどれだけ近いかを観察します。倍精度から.498864ULP(倍精度ULP)離れているため、丸めが変化するポイントから.001136ULP離れています。したがって、sin
ルーチンにごくわずかな不正確さがあったとしても、より近い0x1.df640d8d36175p-1ではなく0x1.df640d8d36174p-1が返されます。
したがって、不一致の原因はsin
ルーチンの非常に小さな不正確さであると私は推測します。