Cómo comparar representaciones de cadena de dobles si termina en .00

Actualmente estoy escribiendo casos de prueba para un ContentProvider en mi aplicación (que es una aplicación de registro de chequera) y estoy teniendo un fallo de prueba cuando se compara valores dobles. La mejor manera de ilustrar esto es con el código. Tengo esta función que devuelve ContentValues ​​para que un objeto de la cuenta se inserte en la base de datos:

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; } 

Dentro de una función testInsertReadProvider() Tengo el siguiente código, para insertar esa cuenta:

 // 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(); 

La función de cursor de validación toma un cursor y un ContentValues ​​y loops a través de ellos utilizando un mapa para comparar cada valor. Esta es una estrategia que aprendí de seguir un tutorial de Udacity en la creación de aplicaciones de Android, así que tal vez hay una mejor manera de compararlos en lugar de como cadenas, pero se ve así:

 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(); } 

La prueba está fallando cuando la línea assertEquals() se llama y obtiene el siguiente mensaje de error:

Junit.framework.ComparisonFailure: esperado: <3000 [.0]> pero fue: <3000 []>

Parece que el método cursor.getString () está truncando los lugares decimales si son iguales a 0. Si intento esta prueba usando un valor de 3000.01 funciona bien. SQLite es responsable de dejar caer los ceros innecesarios? ¿Puedo cambiar el assertEquals() de alguna manera para que esos dos valores sean tratados iguales?

2 Solutions collect form web for “Cómo comparar representaciones de cadena de dobles si termina en .00”

Si realmente te apetece comparar cadenas, de lo que tendrás que cortar un poco, pero hay una alternativa a continuación.

Primero, aquí está el TL; DR; código:

  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)); } } 

Lo que probablemente está ocurriendo es que cada instancia de su double está al final proyectada a String por un método diferente toString() . Eso es lo que causa las irregularidades.

Usted puede cortarlo como he descrito anteriormente o hacer la comparación en una declaración de switch específicamente diseñado para cada tipo (IMHO una mejor solución) .

Aquí está la versión Switch :

 for(Map.Entry<String, Object> entry : valueSet){ String columnName = entry.getKey(); int idx = valueCursor.getColumnIndex(columnName); assertFalse(idx == -1); switch(valueCursor.getType(idx)) { case Cursor.FIELD_TYPE_FLOAT: assertEquals(entry.getValue(), valueCursor.getDouble(idx)); break; case Cursor.FIELD_TYPE_INTEGER: //assertEquals(entry.getValue(), valueCursor.getInt(idx)); // didn't work //assertTrue((new Integer((int)entry.getValue())).equals(valueCursor.getInt(idx))); assertEquals(Integer.parseInt(entry.getValue().toString()), valueCursor.getInt(idx)); case Cursor.FIELD_TYPE_STRING: assertEquals(entry.getValue(), valueCursor.getString(idx)); break; default: assertEquals(entry.getValue().toString(), valueCursor.getString(idx)); } } 

Deberá transferirlos a dobles usando

double d1 = Double.parseDouble(text) double d2 = Double.parseDouble(text2)

Haga lo mismo con la segunda cadena y compare los resultados. También puede utilizar abs para asegurarse de que no hay diferencia debido a la representación:

assertTrue(Math.abs(d1 -d2) < 0.00001);

EDITAR:

Yo iría para algo como esto:

 try { double d1 = Double.parseDouble(text); double d2 = Double.parseDouble(text2); assertTrue(Math.abs(d1-d2) < 0.00001); }catch(NumberFormatException e) { assertEquals(text, text2); } 
  • SQLite de Android Cursor fuera de límites de excepción en SELECT count (*) FROM table
  • Android Sqlite obtiene la última inserción de fila id
  • Obtención de la excepción de base de datos de Sqlite en Android
  • ¿Cómo funciona un cursor SQLite trabajar internamente?
  • Android One Plus Two: No se pudo cambiar la configuración regional para db
  • Android ContentProvider Esquema de URI para notificar a CursorAdapters escuchando consultas de OUTER JOIN
  • ¿Qué técnica de almacenamiento de datos Android utilizar?
  • Se eliminó la base de datos de Sqlite cuando borro datos de la aplicación
  • Selección de valores NULL en Android SQLite
  • Demasiados argumentos de enlace. 5 argumentos fueron proporcionados, pero la declaración necesita 4 argumentos
  • Contactos de Android: Colocación / clasificación local incorrecta
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.