6

Haskell 関数に関する問題がfloorあります。「引数よりも大きくない最大の整数」を返すはずですが、式は

floor 3.9999999999999999

3 ではなく 4 を返します。Double型の精度に関係している可能性がありますが、Haskell の型安全性の重要性を考えるとコンパイルすべきではありません。とにかく、この場合、その定義に矛盾する引数よりも大きい数値を返します。

4

2 に答える 2

22

この場合、その定義に矛盾する引数よりも大きい数値を返します。

引数に等しい数値を返します。あなたが言ったように、それは倍精度についてです。数値 3.9999999999999999 と 4 は、64 ビット浮動小数点規則の下では単純に互いに等しくなります。

しかし、Haskell の型安全性の重要性を考えると、コンパイルすべきではありません。

問題は、そのような小数リテラルが多相型を持つことFractional a => aです。つまり、ダブルである必要はありません。たとえば、floor (3.9999999999999999 :: Rational)3.9999999999999999 は精度を損なうことなく a として表すことができるため、正しく 3 を返す と書くことができますRational

もし Haskell が を書くことをエラーにし3.9999999999999999たら、あなたも を書くことができなくなり3.9999999999999999 :: Rational、それは悪いことです。したがって、Fractionalリテラルは多くの異なる型を使用して表すことができ、そのうちのいくつかは無限の精度を持つため、Haskell がの制限にFractional基づいて正当なリテラルの数を制限するのは大きな間違いですDouble

Haskell は として使用する場合は制限すべきで、3.9999999999999999として使用する場合は制限すべきではないと主張する人もいるかもしれません。ただし、これには型クラスのインスタンスが精度に関する情報を宣言する必要があり (Haskell がその情報を使用して、指定されたリテラルがその型に対して有効かどうかを判断できるようにするため)、現在はそうではなく、困難 (または不可能) です。一般的で効率的かつユーザーフレンドリーな方法で実装する (「精度」という用語は、浮動小数点数と固定小数点数のどちらについて話しているか、基数 2 と 10 のどちらを使用しているかによって、まったく異なる意味になる可能性があることを考慮して) (またはその他のもの) を使用して数値を表します - どちらも型クラスのインスタンスで可能です)。DoubleRationalFractionalFractional

于 2013-04-23T10:26:09.543 に答える
9

これは型安全性とは関係ありません。たとえば、 http://babbage.cs.qc.cuny.edu/IEEE-754/の値を確認してください。長さが 64 ビット以下の場合、浮動小数点数の3.9999999999999999との値はまったく同じです。4返される値は大きくはなく、まったく同じです。

このような高い精度が必要な場合は、http: //www.haskell.org/haskellwiki/Libraries_and_tools/Mathematics#Arbitrary_precision をご覧ください。

于 2013-04-23T10:26:21.233 に答える