7

たとえばx = 0.56657011973046234、sqliteデータベースにdouble値を格納し、後でそれを取得すると、が取得されることに気付きましたy = 0.56657011973046201sqlite仕様.NET仕様(どちらも私が最初に読んだことはありません:)によると、これは予想されたものであり、正常です。

私の問題は、高精度は重要ではありませんが、私のアプリは、ユーザーが基本的な3D情報を表すdoubleを入力/選択し、シミュレーションを実行して結果を見つけることを処理することです。そして、この入力はsqliteデータベースに保存して、後で再ロードして再実行することができます。

新しく作成された一連の入力は、保存および再ロードされると(double値が変更されたため)、同じ入力とは明らかに異なる方法でシミュレートされるため、混乱が生じます。これは論理的ですが、望ましくありません。

私はこれにどう対処するかについては完全には理解していませんが、それまでの間、ユーザー入力をsqliteデータベースに正確に格納できる値に制限/クランプしたいと思います。したがって、ユーザーが入力する0.56657011973046234と、実際にはに変換され0.56657011973046201ます。

しかし、実際にデータベースに格納してデータベースから取得する以外に、データベースに格納される値を数値で把握することはできませんでした。これは不格好なようです。これを行うための確立された方法はありますか?

4

6 に答える 6

3

答えは、double値を17の有効数字列として格納することです。SQLiteが実数とテキストを処理する方法の違いを見てください(簡単にするために、コマンドラインインターフェイスで説明します)。

sqlite> create table t1(dr real, dt varchar(25));
sqlite> insert into t1 values(0.56657011973046234,'0.56657011973046234');
sqlite> select * from t1;
0.566570119730462|0.56657011973046234

本当の親和性でそれを保存することはあなたの問題の原因です-SQLiteはあなたに15桁の概算しか返しません。代わりにテキストとして保存する場合は、C#プログラムで元の文字列を取得し、元のdoubleに変換して戻すことができます。

于 2010-12-03T00:34:04.400 に答える
2

SQL Liteと.NETの両方がIEEE仕様を正しく実装していると仮定すると、両側で同じ浮動小数点型を使用した場合、同じ数値結果を得ることができるはずです(データベースから渡されるときに値が変更されるべきではないため) C#に、またはその逆)。

現在、SQL Liteでは8バイトのIEEE浮動小数点(シングル)(*)を使用し、C#では16バイトの浮動小数点(ダブル)を使用しています。C#のfloatタイプは8バイトのIEEE標準に対応しているため、代わりにこのタイプを使用doubleすると問題を解決できます。

(*)SQL Liteのドキュメントには、REALは浮動小数点値であり、8バイトのIEEE浮動小数点数として格納されると記載されています。

于 2010-11-17T01:43:59.853 に答える
2

ダブルラウンドには、桁数を指定するパラメーターを使用した実装があります。これを使用して、次のように14桁に丸めます(たとえば):rval = Math.Round(Val、14)

次に、データベースから値を受け取ったとき、およびシミュレーションの開始時に丸めます。それで、値が一致するとき?

詳細については:

http://msdn.microsoft.com/en-us/library/75ks3aby.aspx

データベース内の値を比較せず、単にそれらを格納する場合の別の考え:単純にバイナリデータとして格納しないのはなぜですか?次に、すべてのビットがそのまま保存および復元されますか?

于 2010-11-17T01:45:38.027 に答える
1

文字列を使用して、データベースに#を格納できます。個人的には、保存前とデータベース(numeric()を使用)からのフェッチ後に、winwaedが提案した丸めを実行しました。

銀行家の丸めによって火傷を負ったことを思い出しますが、それは仕様を満たしていない可能性があります。

于 2010-11-17T01:48:34.897 に答える
1

doubleを文字列として格納できます。また、doubleを文字列に変換するときにラウンドトリップ形式を使用することで、解析時に同じ値が生成されることが保証されます。

string formatted = theDouble.ToString("R", CultureInfo.Invariant);
于 2010-11-17T02:06:21.000 に答える
1

10進数の入力値をラウンドトリップする場合は、有効数字15桁に制限する必要があります。SQLiteの内部倍精度浮動小数点値をラウンドトリップする場合は、運が悪い可能性があります。最小17桁の有効数字で印刷する必要がありますが、私が知る限り、SQLiteは最大15桁で印刷します(編集SQLiteの専門家がこれを確認できるかもしれませんか?ソースコードを読んでトレースしただけです-私は正解です。精度は15桁に制限されています。)

WindowsのSQLiteコマンドインターフェイスで例をテストしました。0.56657011973046234を挿入し、選択すると0.566570119730462が返されました。Cでは、0.566570119730462をdoubleに割り当て、17桁で印刷すると、0.56657011973046201になりました。これは、C#から取得する値と同じです。0.56657011973046234と0.56657011973046201は異なる浮動小数点数にマップされるため、つまり、SQLitedoubleはラウンドトリップしません。

于 2010-11-18T16:15:51.157 に答える