[英]android sqlite BigDecimal: convert from double or text without loss of precision
創建表Foo(productName文本,價格數字)
如何在Android中將價格轉換為BigDecimal?
new BigDecimal(cursor.getString(1))
or
new BigDecimal(cursor.getDouble(1))
它不應該失去精度。
簡而言之,不丟失精度的唯一方法是在為NUMERIC列保存數據時欺騙SQlite。
假定值value 1234567890.1234567890 SQLite將根據數字親和力將其存儲為字符串或雙精度值,具體如下:
具有NUMERIC關聯性的列可能包含使用所有五個存儲類的值。 將文本數據插入NUMERIC列時,如果這種存儲無損且可逆,則將文本的存儲類轉換為INTEGER或REAL(按優先順序)。 對於TEXT和REAL存儲類之間的轉換,如果保留該數字的前15個有效十進制數字,則SQLite認為轉換是無損且可逆的。 如果無法將TEXT無損地轉換為INTEGER或REAL,則使用TEXT存儲類存儲該值。 沒有嘗試轉換NULL或BLOB值。
通過getDouble
檢索值將導致精度損失,從而導致Big Decimal傳遞的值為1234567890.1234567165374755859375 (請參見下面的輸出)。
通過getString
檢索值將導致精度損失,從而導致Big Decimal傳遞的值為1.23457e + 09 (請參見下面的輸出)。
解決此問題的方法是愚弄 SQLITE,例如保存MYNUMB = 1234567890.1234567890 ,將另存為TEXT,然后可以將其檢索為原始字符串,去除MYNUMB =並用於將BIG DECIMAL設置為1234567890.1234567890 。
以下代碼可能有意義或有用,可用於確定上述內容:-
public class MainActivity extends AppCompatActivity {
DBHelper mydbhlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get DBHelper
mydbhlpr = new DBHelper(this);
// Empty table
mydbhlpr.getWritableDatabase().delete(DBHelper.TBNAME,null,null);
// Insert value as a string
ContentValues cv = new ContentValues();
cv.put(DBHelper.PRODUCTNAME_COL,"myproduct");
cv.put(DBHelper.PRICE_COL,"1234567890.1234567890");
cv.put(DBHelper.COMMENTS_COL,"DATA INPUT AS STRING");
mydbhlpr.insertRow(cv);
cv.clear();
// insert value as a double
cv.put(DBHelper.PRODUCTNAME_COL,"myproduct");
cv.put(DBHelper.PRICE_COL,1234567890.1234567890D);
cv.put(DBHelper.COMMENTS_COL,"DATA INPUT AS DOUBLE");
mydbhlpr.insertRow(cv);
// alternative insert method with value as a string
mydbhlpr.getWritableDatabase().execSQL(
"INSERT INTO " + DBHelper.TBNAME + "(" +
DBHelper.PRODUCTNAME_COL + "," +
DBHelper.PRICE_COL + "," +
DBHelper.COMMENTS_COL +
")" +
" VALUES('myproduct','1234567890.1234567890','ALTERNATE INPUT STR')"
);
// alternative insert method with value as numeric (i.e. not in quotes)
mydbhlpr.getWritableDatabase().execSQL(
"INSERT INTO " + DBHelper.TBNAME + "(" +
DBHelper.PRODUCTNAME_COL + "," +
DBHelper.PRICE_COL + "," +
DBHelper.COMMENTS_COL +
")" +
" VALUES('myproduct',1234567890.1234567890,'ALTERNATE INPUT NUM')"
);
// method to force store numeric data (would need to strip MYNUM= before convert)
mydbhlpr.getWritableDatabase().execSQL(
"INSERT INTO " + DBHelper.TBNAME + "(" +
DBHelper.PRODUCTNAME_COL + "," +
DBHelper.PRICE_COL + "," +
DBHelper.COMMENTS_COL +
")" +
" VALUES('myproduct','MYNUM=1234567890.1234567890','FOOLIT INPUT NUM')"
);
mydbhlpr.retrieveData();
}
}
這基本上填充表(見DBHelper)配有5行,然后調用retrieveData
方法輸出轉換結果到Log為表中的每一行。
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "bigdecimal";
public static final String TBNAME = "bd";
public static final String PRODUCTNAME_COL = "productName";
public static final String PRICE_COL = "price";
public static final String COMMENTS_COL = "comments";
public static final int DBVERSION = 1;
SQLiteDatabase mDB;
DBHelper(Context context) {
super(context,DBNAME,null,DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String tblcrtsql = "CREATE TABLE IF NOT EXISTS " + TBNAME + "(" +
PRODUCTNAME_COL + " TEXT, " +
PRICE_COL + " NUMERIC, " +
COMMENTS_COL + " TEXT" +
")";
db.execSQL(tblcrtsql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public void insertRow(ContentValues cv) {
mDB.insert(TBNAME,null,cv);
}
public void retrieveData() {
String priceasstr;
Double priceasdbl;
BigDecimal bdstrprice, bddblprice;
DecimalFormat df = new DecimalFormat("#.000000000000");
Cursor csr = mDB.query(TBNAME,null,null,null,null,null,null);
while (csr.moveToNext()) {
priceasstr = csr.getString(csr.getColumnIndex(PRICE_COL));
priceasdbl = csr.getDouble(csr.getColumnIndex(PRICE_COL));
try {
bdstrprice = new BigDecimal(priceasstr);
} catch (Exception e) {
Log.d("OOOPS","extracted data not a valid number");
String extracted = priceasstr.substring(6);
bdstrprice = new BigDecimal(extracted);
}
bddblprice = new BigDecimal(priceasdbl);
Log.d("ROWINFO",
"Row = " + Integer.toString(csr.getPosition()) +
". Commentary: " + csr.getString(csr.getColumnIndex(COMMENTS_COL)) +
"\n\tValue extracted as String = " + priceasstr +
"\n\tValue extracted as Double = " + Double.toString(priceasdbl) +
"\n\t formatted from Double = " + df.format(priceasdbl) +
"\n\tBD via getString = " + bdstrprice.toString() +
"\n\tBD via getDouble = " + bddblprice.toString() +
"\n\tBDF via getString = " + df.format(bdstrprice) +
"\n\tBDF via getDouble = " + df.format(bddblprice)
);
}
csr.close();
}
}
10-05 18:41:18.392 4535-4535/mjt.so46593121 D/ROWINFO: Row = 0. Commentary: DATA INPUT AS STRING
Value extracted as String = 1.23457e+09
Value extracted as Double = 1.2345678901234567E9
formatted from Double = 1234567890.123456700000
BD via getString = 1.23457E+9
BD via getDouble = 1234567890.1234567165374755859375
BDF via getString = 1234570000.000000000000
BDF via getDouble = 1234567890.123456716537
10-05 18:41:18.392 4535-4535/mjt.so46593121 D/ROWINFO: Row = 1. Commentary: DATA INPUT AS DOUBLE
Value extracted as String = 1.23457e+09
Value extracted as Double = 1.2345678901234567E9
formatted from Double = 1234567890.123456700000
BD via getString = 1.23457E+9
BD via getDouble = 1234567890.1234567165374755859375
BDF via getString = 1234570000.000000000000
BDF via getDouble = 1234567890.123456716537
10-05 18:41:18.392 4535-4535/mjt.so46593121 D/ROWINFO: Row = 2. Commentary: ALTERNATE INPUT STR
Value extracted as String = 1.23457e+09
Value extracted as Double = 1.2345678901234567E9
formatted from Double = 1234567890.123456700000
BD via getString = 1.23457E+9
BD via getDouble = 1234567890.1234567165374755859375
BDF via getString = 1234570000.000000000000
BDF via getDouble = 1234567890.123456716537
10-05 18:41:18.392 4535-4535/mjt.so46593121 D/ROWINFO: Row = 3. Commentary: ALTERNATE INPUT NUM
Value extracted as String = 1.23457e+09
Value extracted as Double = 1.2345678901234567E9
formatted from Double = 1234567890.123456700000
BD via getString = 1.23457E+9
BD via getDouble = 1234567890.1234567165374755859375
BDF via getString = 1234570000.000000000000
BDF via getDouble = 1234567890.123456716537
10-05 18:41:18.392 4535-4535/mjt.so46593121 D/OOOPS: extracted data not a valid number
10-05 18:41:18.392 4535-4535/mjt.so46593121 D/ROWINFO: Row = 4. Commentary: FOOLIT INPUT NUM
Value extracted as String = MYNUM=1234567890.1234567890
Value extracted as Double = 0.0
formatted from Double = .000000000000
BD via getString = 1234567890.1234567890
BD via getDouble = 0
BDF via getString = 1234567890.123456789000
BDF via getDouble = .000000000000
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.