Java 如果double以.00结尾,如何比较double的字符串表示形式

Java 如果double以.00结尾,如何比较double的字符串表示形式,java,android,sqlite,testing,android-sqlite,Java,Android,Sqlite,Testing,Android Sqlite,我目前正在为我的应用程序(这是一个支票簿记录应用程序)中的一个ContentProvider编写测试用例,当它比较两个值时,我的测试失败了。说明这一点的最佳方法是使用代码。我有一个函数,它返回要插入数据库的account对象的ContentValues: private ContentValues getAccountContentValues(){ String testName = "Capital One"; double testStartingBalance = 3000.

我目前正在为我的应用程序(这是一个支票簿记录应用程序)中的一个ContentProvider编写测试用例,当它比较两个值时,我的测试失败了。说明这一点的最佳方法是使用代码。我有一个函数,它返回要插入数据库的account对象的ContentValues:

private ContentValues getAccountContentValues(){
   String testName = "Capital One";
   double testStartingBalance = 3000.00;

   ContentValues accountValues = new ContentValues();
   accountValues.put(AccountEntry.COLUMN_NAME, testName);
   accountValues.put(AccountEntry.COLUMN_BALANCE, testStartingBalance);

   return accountValues;
}
在函数
testInsertReadProvider()
中,我有以下代码来插入该帐户:

// Get Account values and write them
ContentValues accountValues = getAccountContentValues();
Uri accountInsertUri = 
        mContext.getContentResolver().insert(AccountEntry.CONTENT_URI, accountValues);
long accountRowId = ContentUris.parseId(accountInsertUri);

// Verify we got a row back
assertTrue(accountRowId > 0);

// A cursor is the primary interface to the query results
Cursor cursor = mContext.getContentResolver().query(
        AccountEntry.CONTENT_URI, // Table name
        null, // columns to be returned. Null returns all columns
        null, // Columns for where clause
        null, // Values for where clause
        null // Sort order
);

// Validate the information read from the database.
validateCursor(cursor, accountValues);
cursor.close();
validate cursor函数获取一个游标和一个ContentValues,并使用映射对它们进行循环以比较每个值。这是我从创建Android应用程序的Udacity教程中学到的一个策略,因此也许有更好的方法来比较它们,而不是作为字符串,但它看起来像这样:

void validateCursor(Cursor valueCursor, ContentValues expectedValues){
   assertTrue(valueCursor.moveToFirst());

   Set<Map.Entry<String, Object>> valueSet = expectedValues.valueSet();

   for(Map.Entry<String, Object> entry : valueSet){
       String columnName = entry.getKey();
       int idx = valueCursor.getColumnIndex(columnName);
       assertFalse(idx == -1);
       String expectedValue = entry.getValue().toString();
       assertEquals(expectedValue, valueCursor.getString(idx));
   }
   valueCursor.close();
}
try
{
   double d1 = Double.parseDouble(text);
   double d2 = Double.parseDouble(text2);
   assertTrue(Math.abs(d1-d2) < 0.00001);

}catch(NumberFormatException e)
{
    assertEquals(text, text2);
}
void validateCursors(游标值游标,ContentValues expectedValues){
assertTrue(valueCursor.moveToFirst());
Set valueSet=expectedValues.valueSet();
for(Map.Entry:valueSet){
String columnName=entry.getKey();
int idx=valueCursor.getColumnIndex(columnName);
assertFalse(idx==-1);
字符串expectedValue=entry.getValue().toString();
assertEquals(expectedValue、valueCursor.getString(idx));
}
valueCursor.close();
}
调用
assertEquals()
行时,测试失败,我收到以下错误消息:

junit.framework.ComparisonFailure:应为:但 是:


如果小数位数等于0,则cursor.getString()方法似乎正在截断小数位数。如果我尝试使用3000.01的值进行此测试,效果很好。SQLite是否负责删除不必要的零?我能否以某种方式更改assertEquals(),使这两个值被视为相同的值?

您应该使用

double d1=double.parseDouble(文本)
double d2=double.parseDouble(text2)

对第二个字符串执行相同的操作并比较结果。您也可以使用abs,以确保没有因表现而产生的差异:

assertTrue(数学abs(d1-d2)<0.00001)

编辑:

我会选择这样的方式:

void validateCursor(Cursor valueCursor, ContentValues expectedValues){
   assertTrue(valueCursor.moveToFirst());

   Set<Map.Entry<String, Object>> valueSet = expectedValues.valueSet();

   for(Map.Entry<String, Object> entry : valueSet){
       String columnName = entry.getKey();
       int idx = valueCursor.getColumnIndex(columnName);
       assertFalse(idx == -1);
       String expectedValue = entry.getValue().toString();
       assertEquals(expectedValue, valueCursor.getString(idx));
   }
   valueCursor.close();
}
try
{
   double d1 = Double.parseDouble(text);
   double d2 = Double.parseDouble(text2);
   assertTrue(Math.abs(d1-d2) < 0.00001);

}catch(NumberFormatException e)
{
    assertEquals(text, text2);
}
试试看
{
double d1=double.parseDouble(文本);
double d2=double.parseDouble(text2);
资产真实性(数学绝对值(d1-d2)<0.00001);
}捕获(数字格式)
{
资产质量(文本,文本2);
}
如果您真的想比较字符串,那么您必须稍微修改一下,但下面有一个替代方案。 首先,这里是TL;博士代码:

    for(Map.Entry<String, Object> entry : valueSet){
        String columnName = entry.getKey();
        int idx = valueCursor.getColumnIndex(columnName);
        assertFalse(idx == -1);
        String expectedValue = entry.getValue().toString();
        if((Cursor.FIELD_TYPE_FLOAT == valueCursor.getType(idx))
                && valueCursor.getDouble(idx) % 1 == 0){
            assertEquals(expectedValue, valueCursor.getString(idx) + ".0");
        } else {
            assertEquals(expectedValue, valueCursor.getString(idx));
        }
    }

如果我这样做,它将需要对
validateCursors()
函数进行彻底的修改,因为它并不总是比较双精度。有时它们是字符串或整数,这就是为什么为了简单起见,该函数只是将所有内容转换回字符串。我相信你所说的会起作用,我只是希望能有一种方法来确保字符串之间的比较有效。但是double可以是一个整数值,所以如果你有string=“123”,它会起作用。但是什么是包含字符串的列呢?我不能在alpha字符串上调用
Double.parseDouble()
,对吗?写一个case语句来检查要比较的列并不难,我可以将它们分成不同的类型,并以这种方式进行比较,但当我添加更多的列和表时,该方法可能会变得非常庞大。在这种情况下,通用解决方案不起作用。正如您所说,您必须检查正在检查的列。我想它不会太大。问题只会出现在浮球和双打上。您只需要一个标志来检查该情况,然后为该情况添加一个额外的断言。经过一些测试:截断的是valueCursor.getString(idx),因此我必须将.00添加到该字段中。在测试之后,我只需要添加“.0”,因为即使是Double.toString()也会将其更改为“3000.0”。我认为你是对的,switch语句会更好。由于我知道哪些列对应于每种类型,因此最好根据
columnName
执行切换吗?我可能会切换行类型,然后无论您有多少列,您都已经对任何可能的值进行了测试。我将在答案中添加这个变量。避免货币的双精度是不是一种更好的做法,因为存在这样的问题以及浮点精度错误?@cantido什么是替代方案?Java有一个
currency
类,还有Joda Money。这个问题涉及表示货币:@cantido如果我使用currency类,我将在数据库中存储它作为什么?Text?这两个类都遵循表示金额的格式,因此您可能将它们存储为该格式的文本