创建表格Foo(productName文本,价格数字)
如何在Android中将价格转换为BigDecimal?
new BigDecimal(cursor.getString(1))
or
new BigDecimal(cursor.getDouble(1))
它不应该失去精确度。
答案 0 :(得分:0)
简而言之,不失精度的唯一方法是在保存NUMERIC列的数据时欺骗SQlite。
假设值 1234567890.1234567890 SQLite将根据数字亲和关系将其存储为字符串或双精度: -
具有NUMERIC亲和力的列可能包含使用全部五个值的值 存储类。当文本数据插入NUMERIC列时, 文本的存储类转换为INTEGER或REAL(按顺序) (如果这种转换是无损且可逆的)。对于 SQLite认为,TEXT和REAL存储类之间的转换 如果前15个转换为无损且可逆转 保留该数字的有效十进制数字。如果 无法将TEXT无损转换为INTEGER或REAL 使用TEXT存储类存储该值。没有尝试 转换NULL或BLOB值。
Datatypes In SQLite Version 3 - 3. Type Affinity
通过 getDouble
检索值会导致精度损失,从而导致大十进制值传递 1234567890.1234567165374755859375 (请参阅下面的输出)。
通过 getString
检索值会导致精度下降,从而导致大十进制值传递 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();
}
}
这基本上用5行填充表(参见DBHelper),然后调用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