簡體   English   中英

android sqlite BigDecimal:從雙精度或文本轉換而不會損失精度

[英]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值。

SQLite版本3-3中的數據類型。

通過getDouble檢索值將導致精度損失,從而導致Big Decimal傳遞的值為1234567890.1234567165374755859375 (請參見下面的輸出)。

通過getString檢索值將導致精度損失,從而導致Big Decimal傳遞的值為1.23457e + 09 (請參見下面的輸出)。

如何愚弄SQLite

解決此問題的方法是愚弄 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM