Как систематизировать проверку «а вполне равно b» (либо методом округления, либо | a - b | ~ 0) для любого значения a?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как систематизировать проверку «а вполне равно b» (либо методом округления, либо | a - b | ~ 0) для любого значения a?

Сообщение Anonymous »

Мой контекст
Я реализовал метод равенства(Object o) для объекта скорости (Vitesse здесь), что, когда он сталкивается с сравниваемым значением в м/с, когда оно само в км/ч (в примере), перед сравнением значений также помещается сравниваемое значение в км/ч. И я тестирую его в этом тесте, где он запускается последним оператором AssertEquals(...):
@Test
@DisplayName("Ex E1, Benson Ch. 3")
void ex_Benson_Ch3_E1() {
LOGGER.info("Asafa Powell (Jamaïque) court 100m en 9.74s. Quelle est sa vitesse moyenne ?\nSerait-il en infraction dans une zone scolaire où la vitesse est limitée à 30 km/h ?");

Vitesse vitesseMoyenne = new Vitesse(100, 9.74); // Par défaut, en mètres secondes
assertEquals(10.3, vitesseMoyenne.vitesse(), 0.1, "La vitesse moyenne du coureur n'est pas la bonne, en m/s");

// Vérifier les conversions, étape par étape
Vitesse v1 = new Vitesse(vitesseMoyenne);

v1.convertir(KILOMETRE);
assertEquals(0.0103, v1.vitesse(), 0.1, "La vitesse moyenne du coureur n'est pas la bonne, en km/s");
assertEquals("km/s", v1.uniteMesure().symbole(), "La vitesse moyenne du coureur n'est pas exprimée en km/s");

v1.convertir(HEURE);
assertEquals(36.961, v1.vitesse(), 0.001, "La vitesse moyenne du coureur n'est pas la bonne, en km/h (A)");
assertEquals("km/h", v1.uniteMesure().symbole(), "La vitesse moyenne du coureur n'est pas exprimée en km/h (A)");

// Vérifier la conversion d'un seul tenant
Vitesse v2 = new Vitesse(vitesseMoyenne);

v2.convertir(KILOMETRE, HEURE);
assertEquals(36.961, v2.vitesse(), 0.001, "La vitesse moyenne du coureur n'est pas la bonne, en km/h (B)");
assertEquals("km/h", v2.uniteMesure().symbole(), "La vitesse moyenne du coureur n'est pas exprimée en km/h (B)");

if (v2.vitesse() > 36.0) {
LOGGER.info("Il serait bien en infraction dans une zone limitée à 30 km/h !");
}
else {
Assertions.fail("Il aurait dû être en infraction dans une zone limitée à 30 km/h");
}

// La vitesse moyenne, qui est restée en m/s, doit être égale à celle en km/h.
assertEquals(vitesseMoyenne, v2, "La vitesse moyenne du coureur, en m/s, doit être la même que celle en km/h, car une conversion est attendue durant la comparaison");
}

Моя проблема
Где-то в методе равенства возврат v == this.valeur.doubleValue() отвечает (правильно!) false, потому что из:

объекта this со значением 10,266940451745379 м/с

и o параметр для метода Equals со значением 36,96098562628337 км/ч

который следует считать равным после преобразования, он сравнивает в конечном итоге 10,26694045174538 км/ч с 10,266940451745379 км/ч... чьи четыре последних десятичных знака не равны.

Мой вопрос
В данном случае я мог бы сказать:

| 10.26694045174538 - 10.266940451745379 | < 0.001
Но мой метод равенства(Объект o), который сравнивает значения и сначала решает преобразовать их в другую единицу измерения, должен работать для любого диапазона значений...
Вывод из | 10.26694045174538 - 10.266940451745379 | < 0,001 верно.
Но что, если сравниваемые два числа были 0,0000005671226 и 0,0000005671425?

| 0.00000056722 - 0.00000056742 | < 0.001 тогда не имел бы смысла.
Я хотел бы знать, как на основе одного из сравниваемых значений я мог бы определить значение, которое следует присвоить правому члену моего неравенства.

Во втором примере это может быть:

| 0.00000056722 - 0.00000056742 | < 0.0000000001Вместо этого .
Сказано по-другому:
Как автоматизировать определение правильного значения c из значения a здесь:

| a - b | < c

чтобы быть уверенным, что эта проверка будет иметь смысл независимо от значения ?

Эпилог: решение, рад вашей помощи!
public boolean equals(Object o) {
if (o instanceof NotionMesurable notion) {
// Nous ne comparons pas le nom ni la description de la notion de base, car ce sont les valeurs qui nous intéressent.

// Si nous avons la même unité de mesure et la même valeur, nous sommes égaux avec la notion candidate.
if (this.uniteMesure.equals(notion.uniteMesure) && this.valeur.equals(notion.valeur)) {
return true;
}

// Mais si nous n'avons pas la même unité de mesure que notre candidat, nous pouvons tenter convertir sa valeur dans la nôtre, pour voir si nous sommes égaux.
// À la condition notre unité de mesure et celle canditate soient compatibles.
try {
Number converti = notion.en(notion.uniteMesure(), this.uniteMesure());

if (converti instanceof Double v && this.valeur instanceof Double) {
double t = this.valeur.doubleValue();

if (v == t) {
return true;
}

if (v == 0 || t == 0) {
return Math.abs(v - t) < 0.001;
}
else {
return Math.abs(v > t ? v / t : t / v) < 1.001;
}
}

if (converti instanceof BigDecimal v && this.valeur instanceof BigDecimal) {
double t = this.valeur.doubleValue();

if (v.equals(this.valeur)) {
return true;
}

if (v.doubleValue() == 0 || t == 0) {
return Math.abs(v.doubleValue() - t) < 0.001;
}
else {
return Math.abs(v.doubleValue() > t ? v.doubleValue() / t : t / v.doubleValue()) < 1.001;
}
}

if (converti instanceof Float v && this.valeur instanceof Float) {
float t = this.valeur.floatValue();

if (v == t) {
return true;
}

if (v == 0 || t == 0) {
return Math.abs(v - t) < 0.001;
}
else {
return Math.abs(v > t ? v / t : t / v) < 1.001;
}
}

if (converti instanceof Long v && this.valeur instanceof Long) {
return v == this.valeur.longValue();
}

if (converti instanceof Integer v && this.valeur instanceof Integer) {
return v == this.valeur.intValue();
}

if (converti instanceof Short v && this.valeur instanceof Short) {
return v == this.valeur.shortValue();
}

if (converti instanceof Byte v && this.valeur instanceof Byte) {
return v == this.valeur.byteValue();
}
}
catch(UnitesDeMesuresIncomparablesException e) {
return false;
}

return false;
}

// S'il nous est donné une valeur et pas une notion, comparer directement la valeur
if (o instanceof Double v && this.valeur instanceof Double) {
return v == this.valeur.doubleValue();
}

if (o instanceof Long v && this.valeur instanceof Long) {
return v == this.valeur.longValue();
}

if (o instanceof Integer v && this.valeur instanceof Integer) {
return v == this.valeur.intValue();
}

if (o instanceof BigDecimal v && this.valeur instanceof BigDecimal) {
return v.equals(this.valeur);
}

if (o instanceof Float v && this.valeur instanceof Float) {
return v == this.valeur.floatValue();
}

if (o instanceof Short v && this.valeur instanceof Short) {
return v == this.valeur.shortValue();
}

if (o instanceof Byte v && this.valeur instanceof Byte) {
return v == this.valeur.byteValue();
}

return false;
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... und-method
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»