5

次のように、Android ベースの SQLite データベースに float を入れています。

private static final String DATABASE_CREATE = 
    "create table " + DATABASE_TABLE + " ("  
                    + KEY_ID + " integer primary key autoincrement, "
                    + KEY_FLOAT  + " REAL, " + ...
...

content.put(KEY_FLOAT, 37.3f);
db.insert(DATABASE_TABLE, null, content);

テーブルをクエリすると:

Cursor cursor = db.query(false, DATABASE_TABLE, 
      new String[] { KEY_ID, KEY_FLOAT, ... },
      KEY_LATITUDE + "=37.3",
      null, null, null, null, null);

カーソルは空に戻ります。float の値を 37.0 に変更すると、正しく動作し、カーソル内のレコードが返されます。

データベース列の仕様を「REAL」から「float」に変更するなどして、これをある程度テストしました。小数点の後に小数部分がある限り、カーソルは空を返します。何が起こっている?

前もって感謝します!

4

5 に答える 5

8

37.0 は 2 進浮動小数点で正確に表現できるため、通常の問題はありません。37.3 は正確に表現できません。データベース内の値が正確に 37.3 ではないため、クエリは一致しません

オプション:

  • そのようなものがSQLiteに存在する場合は、10進数ベースの数値型を使用します(すぐに確認します)
  • 「LATITUDE > 37.29 AND LATITUDE < 37.31」など、クエリで許容範囲を使用してください。2 進浮動小数点値を正確に等しいかどうか比較することは、問題を引き起こすだけです。

編集: docsを確認したところ、SQLite は 10 進数以外の整数型をサポートしていないようです。ただし、他のデータベースの同じ問題に関連するため、その提案は上記に残します。

編集: 独自の数値型を効果的にローリングする Pascal のソリューションは、多くの場合、優れたソリューションです。必要な精度のレベルを計算し、それに応じて乗算/除算します...したがって、小数点以下 2 桁の精度が必要な場合は、値を格納するときに 100 を乗算し、取得後に 100 で除算します。もちろん、クエリは「乗算」形式である必要があります。

于 2010-07-17T07:11:25.453 に答える
1

私は試してみましたが<column> BETWEEN <min> AND <max>、うまくいきました.許容範囲LATITUDE > 37.29 AND LATITUDE < 37.31は私にはうまくいきませんでした. BETWEENしかし、私はこのヒントで試しました。

私の観察:

  1. レコードが 1 つの場合、大なり記号 ( >) が機能しませんでした。
  2. 複数のレコードがある場合、大なり ( >) は完全に機能しました。
于 2011-10-04T14:29:46.490 に答える
1

確かに、float 値が等しいかどうかを比較するのは悪い考えです。

ただし、SQLite は 8 バイトの浮動小数点値(のようなものDOUBLE) を使用しているため、37.0 が 37.3 と等しいと見なされるのは奇妙です。実際のコードで使用されている値を例に合わせて変更しない限り?

LATITUDE精度を自分で適用し、読み取り/書き込み時に値を変換して、10 分の 1 の整数として格納できます...

于 2010-07-17T07:22:23.160 に答える
0

次のことは私のために働いた:

列タイプを Double に設定し、Java の Double データ型を使用して行を挿入します。何とかダブルが効いた…

于 2014-02-20T12:51:09.507 に答える
0

私は同じ問題に直面しました。私の Sqlite 列は FLOAT 型でした。比較を機能させるには、Float 型の Java 変数を double としてキャストする必要がありました。

于 2014-03-09T19:04:39.430 に答える