Error delta double java

Значение дельта или эпсилон аргумента assertEquals для значений типа double У меня вопрос о JUnit assertEquals для проверки значений double . Чтение документации API I можно увидеть: Устарело. Используйте вместо него assertEquals(double expected, double actual, double delta) . (Примечание: в старых версиях документации параметр дельты называется эпсилон) Что означает параметр delta (или epsilon )? […]

Содержание

  1. Значение дельта или эпсилон аргумента assertEquals для значений типа double
  2. 8 ответов
  3. Error delta double java
  4. Assert
  5. assertTrue
  6. assertTrue
  7. assertFalse
  8. assertFalse
  9. assertEquals
  10. assertEquals
  11. assertNotEquals
  12. assertNotEquals
  13. assertNotEquals
  14. assertNotEquals
  15. assertNotEquals
  16. assertNotEquals
  17. assertNotEquals
  18. assertArrayEquals
  19. assertArrayEquals
  20. assertArrayEquals
  21. assertArrayEquals
  22. assertArrayEquals
  23. assertArrayEquals
  24. assertArrayEquals
  25. assertArrayEquals
  26. assertArrayEquals
  27. assertArrayEquals
  28. assertArrayEquals
  29. assertArrayEquals
  30. assertArrayEquals
  31. assertArrayEquals
  32. assertArrayEquals
  33. assertArrayEquals
  34. assertArrayEquals
  35. assertArrayEquals
  36. assertEquals
  37. assertEquals
  38. assertNotEquals
  39. assertEquals
  40. assertEquals
  41. assertEquals
  42. assertEquals
  43. assertEquals
  44. assertEquals
  45. assertNotNull
  46. assertNotNull
  47. assertNull
  48. assertNull
  49. assertSame
  50. assertSame
  51. assertNotSame
  52. assertNotSame
  53. assertEquals
  54. assertEquals
  55. assertThat
  56. assertThat
  57. assertThrows

Значение дельта или эпсилон аргумента assertEquals для значений типа double

У меня вопрос о JUnit assertEquals для проверки значений double . Чтение документации API I можно увидеть:

Устарело. Используйте вместо него assertEquals(double expected, double actual, double delta) .

(Примечание: в старых версиях документации параметр дельты называется эпсилон)

Что означает параметр delta (или epsilon )?

8 ответов

Эпсилон — это значение, на которое могут отличаться 2 числа. Таким образом, он будет утверждать, что истина, пока Math.abs(expected — actual)

Какая это версия JUnit? Я когда-либо видел только дельту, а не эпсилон — но это побочная проблема!

дельта — максимальная разница между ожидаемым и фактическим значениями, при которой оба числа по-прежнему считаются равными.

Вероятно, это перебор, но я обычно использую очень небольшое число, например

Если вы используете утверждения hamcrest, вы можете просто использовать стандартный equalTo() с двумя двойными (он не использует дельта). Однако, если вам нужна дельта, вы можете просто использовать closeTo() (см. javadoc ), например

К вашему сведению, предстоящий JUnit 5 также будет сделать дельту необязательной при вызове assertEquals() с двумя двойными. Реализация (если вам интересно):

Вычисления с плавающей запятой неточны — часто возникают ошибки округления и ошибки из-за представления. (Например, 0,1 не может быть точно представлено в двоичной системе с плавающей запятой.)

Из-за этого прямое сравнение двух значений с плавающей запятой на равенство обычно не является хорошей идеей, потому что они могут отличаться на небольшую величину, в зависимости от того, как они были вычислены.

«Дельта», как она называется в JUnit javadocs описывает допустимую разницу в значениях, чтобы они по-прежнему считались равными. Размер этого значения полностью зависит от сравниваемых значений. При сравнении удвоений я обычно использую ожидаемое значение, деленное на 10 ^ 6.

Дело в том, что два типа double могут не быть в точности равными из-за проблем с точностью, присущих числам с плавающей запятой. С помощью этого значения дельты вы можете контролировать оценку равенства на основе фактора ошибки.

Также некоторые значения с плавающей запятой могут иметь специальные значения, такие как NAN и -Infinity / + Infinity, которые могут влиять на результаты.

Если вы действительно собираетесь сравнить, что два двойных значения в точности равны, лучше сравнить их как длинное представление.

Которая может учитывать эти нюансы.

Я не углублялся в рассматриваемый метод Assert, но могу только предположить, что предыдущий не рекомендуется для такого рода проблем, а новый учитывает их.

Эпсилон — это разница между значениями expected и actual , которую вы можете принять, думая, что они равны. Например, вы можете установить .1 .

Обратите внимание: если вы не занимаетесь математикой, нет ничего плохого в утверждении точных значений с плавающей запятой. Например:

В этом случае вы хотите убедиться, что это действительно MIN_VALUE , а не ноль, или -MIN_VALUE , или MIN_NORMAL , или какое-то другое очень маленькое значение. Ты можешь сказать

Но это приведет к предупреждению об устаревании. Чтобы этого избежать, вы можете вместо этого позвонить assertEquals(Object, Object) :

И, если вы действительно хотите выглядеть умно:

Или вы можете просто использовать утверждения в свободном стиле Hamcrest:

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

Источник

Error delta double java

A set of assertion methods useful for writing tests. Only failed assertions are recorded. These methods can be used directly: Assert.assertEquals(. ) , however, they read better if they are referenced through static import:

Constructor Summary
protected Assert ()
Protect constructor since it is a static only class
Method Summary
static void assertArrayEquals (boolean[] expecteds, boolean[] actuals)
Asserts that two boolean arrays are equal.
static void assertArrayEquals (byte[] expecteds, byte[] actuals)
Asserts that two byte arrays are equal.
static void assertArrayEquals (char[] expecteds, char[] actuals)
Asserts that two char arrays are equal.
static void assertArrayEquals (double[] expecteds, double[] actuals, double delta)
Asserts that two double arrays are equal.
static void assertArrayEquals (float[] expecteds, float[] actuals, float delta)
Asserts that two float arrays are equal.
static void assertArrayEquals (int[] expecteds, int[] actuals)
Asserts that two int arrays are equal.
static void assertArrayEquals (long[] expecteds, long[] actuals)
Asserts that two long arrays are equal.
static void assertArrayEquals (Object[] expecteds, Object[] actuals)
Asserts that two object arrays are equal.
static void assertArrayEquals (short[] expecteds, short[] actuals)
Asserts that two short arrays are equal.
static void assertArrayEquals (String message, boolean[] expecteds, boolean[] actuals)
Asserts that two boolean arrays are equal.
static void assertArrayEquals (String message, byte[] expecteds, byte[] actuals)
Asserts that two byte arrays are equal.
static void assertArrayEquals (String message, char[] expecteds, char[] actuals)
Asserts that two char arrays are equal.
static void assertArrayEquals (String message, double[] expecteds, double[] actuals, double delta)
Asserts that two double arrays are equal.
static void assertArrayEquals (String message, float[] expecteds, float[] actuals, float delta)
Asserts that two float arrays are equal.
static void assertArrayEquals (String message, int[] expecteds, int[] actuals)
Asserts that two int arrays are equal.
static void assertArrayEquals (String message, long[] expecteds, long[] actuals)
Asserts that two long arrays are equal.
static void assertArrayEquals (String message, Object[] expecteds, Object[] actuals)
Asserts that two object arrays are equal.
static void assertArrayEquals (String message, short[] expecteds, short[] actuals)
Asserts that two short arrays are equal.
static void assertEquals (double expected, double actual)
Deprecated. Use assertEquals(double expected, double actual, double delta) instead
static void assertEquals (double expected, double actual, double delta)
Asserts that two doubles are equal to within a positive delta.
static void assertEquals (float expected, float actual, float delta)
Asserts that two floats are equal to within a positive delta.
static void assertEquals (long expected, long actual)
Asserts that two longs are equal.
static void assertEquals (Object[] expecteds, Object[] actuals)
Deprecated. use assertArrayEquals
static void assertEquals (Object expected, Object actual)
Asserts that two objects are equal.
static void assertEquals (String message, double expected, double actual)
Deprecated. Use assertEquals(String message, double expected, double actual, double delta) instead
static void assertEquals (String message, double expected, double actual, double delta)
Asserts that two doubles are equal to within a positive delta.
static void assertEquals (String message, float expected, float actual, float delta)
Asserts that two floats are equal to within a positive delta.
static void assertEquals (String message, long expected, long actual)
Asserts that two longs are equal.
static void assertEquals (String message, Object[] expecteds, Object[] actuals)
Deprecated. use assertArrayEquals
static void assertEquals (String message, Object expected, Object actual)
Asserts that two objects are equal.
static void assertFalse (boolean condition)
Asserts that a condition is false.
static void assertFalse (String message, boolean condition)
Asserts that a condition is false.
static void assertNotEquals (double unexpected, double actual, double delta)
Asserts that two doubles are not equal to within a positive delta.
static void assertNotEquals (float unexpected, float actual, float delta)
Asserts that two floats are not equal to within a positive delta.
static void assertNotEquals (long unexpected, long actual)
Asserts that two longs are not equals.
static void assertNotEquals (Object unexpected, Object actual)
Asserts that two objects are not equals.
static void assertNotEquals (String message, double unexpected, double actual, double delta)
Asserts that two doubles are not equal to within a positive delta.
static void assertNotEquals (String message, float unexpected, float actual, float delta)
Asserts that two floats are not equal to within a positive delta.
static void assertNotEquals (String message, long unexpected, long actual)
Asserts that two longs are not equals.
static void assertNotEquals (String message, Object unexpected, Object actual)
Asserts that two objects are not equals.
static void assertNotNull (Object object)
Asserts that an object isn’t null.
static void assertNotNull (String message, Object object)
Asserts that an object isn’t null.
static void assertNotSame (Object unexpected, Object actual)
Asserts that two objects do not refer to the same object.
static void assertNotSame (String message, Object unexpected, Object actual)
Asserts that two objects do not refer to the same object.
static void assertNull (Object object)
Asserts that an object is null.
static void assertNull (String message, Object object)
Asserts that an object is null.
static void assertSame (Object expected, Object actual)
Asserts that two objects refer to the same object.
static void assertSame (String message, Object expected, Object actual)
Asserts that two objects refer to the same object.
static

void

assertThat (String reason, T actual, Matcher matcher)
Deprecated. use org.hamcrest.MatcherAssert.assertThat()
static

void

assertThat (T actual, Matcher matcher)
Deprecated. use org.hamcrest.MatcherAssert.assertThat()
static

T

assertThrows (Class expectedThrowable, ThrowingRunnable runnable)
Asserts that runnable throws an exception of type expectedThrowable when executed.
static

T

assertThrows (String message, Class expectedThrowable, ThrowingRunnable runnable)
Asserts that runnable throws an exception of type expectedThrowable when executed.
static void assertTrue (boolean condition)
Asserts that a condition is true.
static void assertTrue (String message, boolean condition)
Asserts that a condition is true.
static void fail ()
Fails a test with no message.
static void fail (String message)
Fails a test with the given message.
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Constructor Detail

Assert

Method Detail

assertTrue

Parameters: message — the identifying message for the AssertionError ( null okay) condition — condition to be checked

assertTrue

Parameters: condition — condition to be checked

assertFalse

Parameters: message — the identifying message for the AssertionError ( null okay) condition — condition to be checked

assertFalse

Parameters: condition — condition to be checked

Parameters: message — the identifying message for the AssertionError ( null okay) See Also: AssertionError

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — actual value

assertEquals

Parameters: expected — expected value actual — the value to check against expected

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertNotEquals

Parameters: unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertNotEquals

Parameters: unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — Object array or array of arrays (multi-dimensional array) with expected values. actuals — Object array or array of arrays (multi-dimensional array) with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — Object array or array of arrays (multi-dimensional array) with expected values actuals — Object array or array of arrays (multi-dimensional array) with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — boolean array with expected values. actuals — boolean array with expected values. Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — boolean array with expected values. actuals — boolean array with expected values.

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — byte array with expected values. actuals — byte array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — byte array with expected values. actuals — byte array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — char array with expected values. actuals — char array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — char array with expected values. actuals — char array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — short array with expected values. actuals — short array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — short array with expected values. actuals — short array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — int array with expected values. actuals — int array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — int array with expected values. actuals — int array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — long array with expected values. actuals — long array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — long array with expected values. actuals — long array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — double array with expected values. actuals — double array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal. Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — double array with expected values. actuals — double array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal.

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — float array with expected values. actuals — float array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal. Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — float array with expected values. actuals — float array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal.

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertEquals

Parameters: expected — expected long value. actual — actual long value

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — long expected value. actual — long actual value

assertEquals

assertEquals

assertEquals

Parameters: expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertEquals

Parameters: expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertNotNull

Parameters: message — the identifying message for the AssertionError ( null okay) object — Object to check or null

assertNotNull

Parameters: object — Object to check or null

assertNull

Parameters: message — the identifying message for the AssertionError ( null okay) object — Object to check or null

assertNull

Parameters: object — Object to check or null

assertSame

Parameters: message — the identifying message for the AssertionError ( null okay) expected — the expected object actual — the object to compare to expected

assertSame

Parameters: expected — the expected object actual — the object to compare to expected

assertNotSame

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — the object you don’t expect actual — the object to compare to unexpected

assertNotSame

Parameters: unexpected — the object you don’t expect actual — the object to compare to unexpected

assertEquals

Asserts that two object arrays are equal. If they are not, an AssertionError is thrown with the given message. If expecteds and actuals are null , they are considered equal.

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — Object array or array of arrays (multi-dimensional array) with expected values. actuals — Object array or array of arrays (multi-dimensional array) with actual values

assertEquals

Asserts that two object arrays are equal. If they are not, an AssertionError is thrown. If expected and actual are null , they are considered equal.

Parameters: expecteds — Object array or array of arrays (multi-dimensional array) with expected values actuals — Object array or array of arrays (multi-dimensional array) with actual values

assertThat

Asserts that actual satisfies the condition specified by matcher . If not, an AssertionError is thrown with information about the matcher and failing value. Example: org.hamcrest.Matcher does not currently document the meaning of its type parameter T . This method assumes that a matcher typed as Matcher can be meaningfully applied only to values that could be assigned to a variable of type T .

Type Parameters: T — the static type accepted by the matcher (this can flag obvious compile-time problems such as assertThat(1, is(«a»)) Parameters: actual — the computed value being compared matcher — an expression, built of Matcher s, specifying allowed values See Also: CoreMatchers

assertThat

Asserts that actual satisfies the condition specified by matcher . If not, an AssertionError is thrown with the reason and information about the matcher and failing value. Example: org.hamcrest.Matcher does not currently document the meaning of its type parameter T . This method assumes that a matcher typed as Matcher can be meaningfully applied only to values that could be assigned to a variable of type T .

Type Parameters: T — the static type accepted by the matcher (this can flag obvious compile-time problems such as assertThat(1, is(«a»)) Parameters: reason — additional information about the error actual — the computed value being compared matcher — an expression, built of Matcher s, specifying allowed values See Also: CoreMatchers

assertThrows

Parameters: expectedThrowable — the expected type of the exception runnable — a function that is expected to throw an exception when executed Returns: the exception thrown by runnable Since: 4.13

Источник


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

I’m struggling to understand the API for junit.framework.Assert — probably because my understanding of Maths terminology is weak.
The javadocs state:
assertEquals(double expected, double actual, double delta)
Asserts that two doubles are equal concerning a delta.
What is delta? I think I’m supposed to pass in a double representing the limit that the actual & expected can vary by and still be considered equal.
I can’t remember where I read this or if I made it up.
Is it true? Is it usual to make the acuracy of the delta value more precise than the others, e.g. expected = 4.5, actual = 5.30, delta = 0.009?
Thansk in advance,
Louise

author and iconoclast

Posts: 24204

Mac OS X
Eclipse IDE
Chrome


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

The delta value is indeed the «error» or «uncertainty» allowed in the comparison. Comparing floating point numbers is tricky — exact equality is hard to come by in many cases.
It’s quite common for the delta to be much smaller than the actual values — for no particular reason, I generally use 1e-8, and this works well.

Wanderer

Posts: 18671


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

I’m struggling to understand the API for junit.framework.Assert — probably because my understanding of Maths terminology is weak.
Also because the JUnit javadoc is rather poor, for such a widely used system. Fortunately the source code is available.
In this case, delta is the maximum allowed absolute difference between actual and expected value. So the test is basically

It’s quite common for the delta to be much smaller than the actual values — for no particular reason, I generally use 1e-8, and this works well.
Unless the values you’re comparing are large enough that 1e-8 is below the roundoff error for the datatype. There’s usually a wide range of values that can work acceptably well for delta, but it does depend on what datatype we’re using and what magnitude the expected value has; there are plenty of case where 1e-8 would be completely ineffectual.
Personally I find it much easier to compare floats and doubles using a relative error. Here’s a method I’d use:

Here the test is essentially

I’ve found that 1e-15 seems reasonable for a double; 1e-7 for a float. But higher values may legitmately be necessary in many situations, depending on what types of calculations were involved in generating a number. Error propagation in numeric calculations is probably too complex for this post, so perhaps it’s best to just realize that in many cases you can just set the relative higher if you keep getting errors with a given value. The question you really need to ask is, how much accuracy do you really need? 1e-15 is an extremely small relative error for most applications; often you’d be OK with it as high as 1e-3 or even 1e-2. Depends on the situation; hard to say more.

«I’m not back.» — Bill Harding, Twister

author & internet detective

Posts: 41506

Eclipse IDE
VI Editor
Java


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

Sometimes I cast to int to get around this. (When expecting doubles with no decimal parts)

Does anyone see any problems with this approach? besides the fact that it can’t be used everywhere…

author

Posts: 11962


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

I think you’re making your tests brittle for no real reason. It would be just as easy to provide a delta…

author

Posts: 14112


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

Originally posted by Jeanne Boyarsky:
Sometimes I cast to int to get around this. (When expecting doubles with no decimal parts)

Does anyone see any problems with this approach?

Wouldn’t the following pass? Would it be bad?

The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny — it is the light that guides your way. — Heraclitus

Jeanne Boyarsky

author & internet detective

Posts: 41506

Eclipse IDE
VI Editor
Java


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

Doh! Thanks guys.

Ilja Preuss

author

Posts: 14112


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

You’re welcome!

The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny — it is the light that guides your way. — Heraclitus

(instanceof Sidekick)

Posts: 8791


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

My favorite language ever — REXX — has a SET NUMERIC FUZZ option that sets the compare precision for numbers. I just love the name!

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi

louise rochford

Ranch Hand

Posts: 119


posted 19 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

Thanks for all your help guys


posted 10 years ago

  • Mark post as helpful


  • send pies

    Number of slices to send:

    Optional ‘thank-you’ note:



  • Quote
  • Report post to moderator

The assertEqualsRelative didn’t work when a negative value is expected. Here it is with Math.abs to fix it.

wood burning stoves

У меня вопрос о JUnit assertEquals для проверки значений double. Чтение документации API I можно увидеть:

@Deprecated
public static void assertEquals(double expected, double actual)

Устарело. Используйте вместо него assertEquals(double expected, double actual, double delta).

(Примечание: в старых версиях документации параметр дельты называется эпсилон)

Что означает параметр delta (или epsilon)?

8 ответов

Лучший ответ

Эпсилон — это значение, на которое могут отличаться 2 числа. Таким образом, он будет утверждать, что истина, пока Math.abs(expected - actual) <= epsilon


224

Grim
24 Сен 2021 в 15:55

Какая это версия JUnit? Я когда-либо видел только дельту, а не эпсилон — но это побочная проблема!

Из JUnit javadoc < / а>:

дельта — максимальная разница между ожидаемым и фактическим значениями, при которой оба числа по-прежнему считаются равными.

Вероятно, это перебор, но я обычно использую очень небольшое число, например

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertEquals(123.456, 123.456, DELTA);
}

Если вы используете утверждения hamcrest, вы можете просто использовать стандартный equalTo() с двумя двойными (он не использует дельта). Однако, если вам нужна дельта, вы можете просто использовать closeTo() (см. javadoc < / a>), например

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertThat(123.456, equalTo(123.456));
    assertThat(123.456, closeTo(123.456, DELTA));
}

К вашему сведению, предстоящий JUnit 5 также будет сделать дельту необязательной при вызове assertEquals() с двумя двойными. Реализация (если вам интересно):

private static boolean doublesAreEqual(double value1, double value2) {
    return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}


129

James Bassett
3 Авг 2016 в 00:03

Вычисления с плавающей запятой неточны — часто возникают ошибки округления и ошибки из-за представления. (Например, 0,1 не может быть точно представлено в двоичной системе с плавающей запятой.)

Из-за этого прямое сравнение двух значений с плавающей запятой на равенство обычно не является хорошей идеей, потому что они могут отличаться на небольшую величину, в зависимости от того, как они были вычислены.

«Дельта», как она называется в JUnit javadocs описывает допустимую разницу в значениях, чтобы они по-прежнему считались равными. Размер этого значения полностью зависит от сравниваемых значений. При сравнении удвоений я обычно использую ожидаемое значение, деленное на 10 ^ 6.


58

Steven P.
13 Мар 2013 в 21:08

Дело в том, что два типа double могут не быть в точности равными из-за проблем с точностью, присущих числам с плавающей запятой. С помощью этого значения дельты вы можете контролировать оценку равенства на основе фактора ошибки.

Также некоторые значения с плавающей запятой могут иметь специальные значения, такие как NAN и -Infinity / + Infinity, которые могут влиять на результаты.

Если вы действительно собираетесь сравнить, что два двойных значения в точности равны, лучше сравнить их как длинное представление.

Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));

Или же

Assert.assertEquals(0, Double.compareTo(expected, result));

Которая может учитывать эти нюансы.

Я не углублялся в рассматриваемый метод Assert, но могу только предположить, что предыдущий не рекомендуется для такого рода проблем, а новый учитывает их.


13

Edwin Dalorzo
16 Апр 2011 в 17:37

Эпсилон — это разница между значениями expected и actual, которую вы можете принять, думая, что они равны. Например, вы можете установить .1.


2

Constantiner
16 Апр 2011 в 17:21

Обратите внимание: если вы не занимаетесь математикой, нет ничего плохого в утверждении точных значений с плавающей запятой. Например:

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

В этом случае вы хотите убедиться, что это действительно MIN_VALUE, а не ноль, или -MIN_VALUE, или MIN_NORMAL, или какое-то другое очень маленькое значение. Ты можешь сказать

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

Но это приведет к предупреждению об устаревании. Чтобы этого избежать, вы можете вместо этого позвонить assertEquals(Object, Object):

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

И, если вы действительно хотите выглядеть умно:

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

Или вы можете просто использовать утверждения в свободном стиле Hamcrest:

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

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


2

David Moles
13 Май 2013 в 23:14

Я просто хочу упомянуть замечательную библиотеку AssertJ. Это моя библиотека утверждений для JUnit 4 и 5, которая также элегантно решает эту проблему:

assertThat(actual).isCloseTo(expectedDouble, within(delta))


1

Tim Büthe
24 Ноя 2020 в 12:38

Assert.assertTrue(Math.abs(actual-expected) == 0)


-4

Prakash
7 Июн 2018 в 22:10

Обратите внимание: если вы не занимаетесь математикой, нет ничего плохого в утверждении точных значений с плавающей запятой. Например:

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

В этом случае вы хотите убедиться, что это действительно MIN_VALUE, не ноль или -MIN_VALUE or MIN_NORMAL или какое-то другое очень маленькое значение. Ты можешь сказать

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

но это приведет к предупреждению об устаревании. Чтобы этого не произошло, вы можете позвонить assertEquals(Object, Object) вместо:

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

И, если вы действительно хотите выглядеть умно:

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

Или вы можете просто использовать утверждения в свободном стиле Hamcrest:

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

Если значение, которое вы проверяете делает прийти из выполнения некоторых математических расчетов, используйте эпсилон.

Junit 5’s org.junit.jupiter.Assertions class provides different static assertions method to write test cases.

Please note that you need to use JUnit’s org.junit.Assert class in case of JUnit 4 or JUnit 3 to assert using assertEquals method.

assertEquals usage

Assertions.assertEquals() checks if expected and actual are equal. In case, both are not equal, it will through AssertError.
Please also note that If both are null, they are considered equal.

When you call assertEquals(object1, object2), it use equals method of that type of Object.

For example:
if object1 and object2 are of String type, then String’s equals method will be called to determine equality relation.

String str1=«India»;

String str2=new String(«India»)

Assertions.assertEquals(str1,str2);

In case of Custom objects, it will use custom object’s equals method to determine equality. In case, it does not override equals method, it will use default behaviour of object class i.e. Object identity.

If object1 and object2 are primitives such as boolean, int , long and object1 and object2 will converted to corresponding wrapper classes and object1.equals(object2) will be used.

Floating point Assertions

When you want to compare floating points such as double and float, then you should always use extra parameter delta to avoid rounding off issues while comparing floating points.

public static void assertEquals(double expected, double actual, double delta)

assertEquals overloaded methods

public static void assertEquals(short expected,short actual)
public static void assertEquals(short expected, short actual,String message)
public static void assertEquals(short expected,short actual,Supplier messageSupplier)public static void assertEquals(byte expected,byte actual)
public static void assertEquals(byte expected, byte actual,String message)
public static void assertEquals(byte expected,byte actual,Supplier messageSupplier)public static void assertEquals(int expected,int actual)
public static void assertEquals(int expected, int actual,String message)
public static void assertEquals(int expected,int actual,Supplier messageSupplier)public static void assertEquals(long expected,long actual)
public static void assertEquals(long expected, long actual,String message)
public static void assertEquals(long expected,long actual,Supplier messageSupplier)

public static void assertEquals(char expected,char actual)
public static void assertEquals(char expected, char actual,String message)
public static void assertEquals(char expected,char actual,Supplier messageSupplier)

public static void assertEquals(float expected,float actual)
public static void assertEquals(float expected, float actual,String message)
public static void assertEquals(float expected,float actual,Supplier messageSupplier)
public static void assertEquals(float expected, float actual, float delta)
public static void assertEquals(float expected, float actual, float delta, String message)
public static void assertEquals(float expected, float actual, float delta, Supplier messageSupplier)

public static void assertEquals(double expected,double actual)
public static void assertEquals(double expected, double actual,String message)
public static void assertEquals(double expected,double actual,Supplier messageSupplier)
public static void assertEquals(double expected, double actual, double delta)
public static void assertEquals(double expected, double actual, double delta, String message)
public static void assertEquals(double expected, double actual, double delta, Supplier messageSupplier)

public static void assertEquals(Object expected,Object actual)
public static void assertEquals(Object expected, Object actual,String message)
public static void assertEquals(Object expected,Object actual,Supplier messageSupplier)

Here is simple example

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

package org.arpit.java2blog;

import org.junit.jupiter.api.Assertions;

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.Test;

public class AssertEqualsTest {

AssertEqualsTest aet;

@BeforeEach

public void beforeEachTest()

{

aet = new AssertEqualsTest();

}

public double getSquareRoot(double num)

{

return Math.sqrt(num);

}

    /*

     * Examples for assertEquals

     */

    //public static void assertEquals(double expected, double actual,String message)

    @Test

    public void testSquareRootOf25(){

     double squareRoot25 = aet.getSquareRoot(25.0);

     Assertions.assertEquals(5.0, squareRoot25,«5 should be sqaure root of 25»);

    }

  //public static void assertEquals(double expected, double actual,String message)

    @Test

    public void testSquareRootOf5(){

     double squareRoot5 = aet.getSquareRoot(5.0);

     Assertions.assertEquals(2.236, squareRoot5,«Square root of 5 is incorrect»);

    }

  //public static void assertEquals(double expected, double actual,double delta, String message)

    @Test

    public void testSquareRootOf5WithDelta(){

     double squareRoot5 = aet.getSquareRoot(5.0);

     Assertions.assertEquals(2.236, squareRoot5,0.001,«Square root of 5 is incorrect»);

    }

}

When you run above testcase, you will get below output:
assertEqualsTestOutput

Let’s understand output of each testcase:


testSquareRootOf25 – Pass

As 5 should be square root of 25, so this testcase will pass.


testSquareRootOf5 – Fail

As square root of 5 is 2.23606797749979 and not 2.236, so this testcase will fail.


testSquareRootOf5WithDelta – Pass

As square root of 5 is 2.23606797749979 within delta range of 0.0001 with respect to 2.236, so this testcase will pass.


JUnit assertEquals custom object example
Let’s use assertEquals to compare custom object.

Create a simple class named Country.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

package org.arpit.java2blog.model;

public class Country{

String name;

long population;

public Country(String name, long population) {

super();

this.name = name;

this.population = population;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + (int) (population ^ (population >>> 32));

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Country other = (Country) obj;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

if (population != other.population)

return false;

return true;

}

@Override

public String toString() {

return name +«-«+population;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public long getPopulation() {

return population;

}

public void setPopulation(long population) {

this.population = population;

}

}

Create another class named CountryHelper which have a method to return highest populated Country.This is the method we are going to test.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

package org.arpit.java2blog.model;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

public class CountryHelper {

public Country getHighestPopulatedCountry(List countries)

{

Collections.sort(countries, new Comparator() {

@Override

public int compare(Country c1, Country c2) {

return ((Long)c2.getPopulation()).compareTo(c1.getPopulation());

}

});

return countries.get(0);

}

}

Let’s create our testcase now.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

package org.arpit.java2blog;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.ArrayList;

import java.util.List;

import org.arpit.java2blog.model.Country;

import org.arpit.java2blog.model.CountryHelper;

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.Test;

public class AssertEqualCustomObjectTest {

    CountryHelper ch;

    @BeforeEach

    public void beforeEachTest()

    {

        ch=new CountryHelper();

    }

    @Test

    public void testHighestPopulatedCountry(){

        Country india=new Country(«India»,20000);

        Country china=new Country(«China»,40000);

        Country bhutan=new Country(«Bhutan»,3000);

        Country nepal=new Country(«Nepal»,7000);

        List<Country> countries=new ArrayList<Country>();

        countries.add(india);

        countries.add(china);

        countries.add(bhutan);

        countries.add(nepal);

        assertEquals(china, ch.getHighestPopulatedCountry(countries));

    }

}

When you run above testcase, you will get below output.
AssertEqualsCustomObjectTestOutput
As you can see, we are comparing two countries objects with the help of assertEquals method and As china has highest population, this testcase will pass.
That’s all about Assertions.assertEquals()


Несколько дней назад мне на глаза попался занимательный такой вопрос, касающийся того, каков будет результат выполнения данного кода:

double a = 2.0 - 1.1;

или такого:

double f = 0.0;
for (int i=1; i <= 10; i++) {
	f += 0.1;
}

Вопреки всем моим ожиданиям, ответ: 0.89999999999999991 в первом случае и 0.99999999999999989 во втором.
Для тех, кто хочет узнать почему, а так же еще несколько занимательных фактов про этот тип данных, милости просим.

В общем виде ответ на поставленный выше вопрос будет звучать примерно так: «Подобные ошибки связанны с внутренним двоичным (binary) представлением чисел. Подобно тому, как в десятичной системе нельзя точно представить результат деления 1/3, так и в двоичной системе невозможно точно представить 1/10. Если вам нужно исключить ошибки округления, следует использовать класс BigDecimal».

Существует важное различие между абстрактными вещественными числами, такими как π или 0.2, и типом данных double в Java. Во-первых, платонически-идеальное представление вещественных чисел является бесконечным, в то время как представление в Java ограничено числом бит. Однако точность вычислений является еще более насущной проблемой, чем ограничение на размер чисел. Еще больше «интригует» совершенно оригинальный способ округления чисел, но обо всем по порядку.

Начать, пожалуй, стоит с двоичного представления целых чисел. Этот абзац нам пригодится чуть позже. Итак. Самым простым вариантом представления целых чисел считается так называемый «Прямой код», в котором старший бит используется для записи знака числа (0 — положительное, 1 — отрицательное), а оставшиеся биты используются непосредственно для записи самого значения. Таким образом, число «-9» в восьмиразрядном представлении будет выглядеть как 10001001. Недостатком такого подхода считается наличие двух нулей («+0» и «-0») и усложнение арифметических операций с отрицательными числами. Другим вариантом, интересующим нас, является «Код со сдвигом», в котором, говоря простым языком, мы прибавляем к нашему числу некое константное для данного типа представления число, равное 2^(n-1), где n — число разрядов (бит). В нашем случае, пример с числом «-9» в восьмиразрядном представлении будет выглядеть так:
-9 + 2^(8-1) = -9 + 128 = 119. В двоичном виде получим 01110111. Этот вариант удобен тем, что ноль у нас всего один, однако при арифметических операциях необходимо будет учитывать смещение.

Здесь стоит упомянуть вот о чем. Одной из заявленных целей языка Java является машинная независимость. Вычисления должны приводить к одинаковому результату, независимо от того, какая виртуальная машина их выполняет. Для арифметических вычислений над числами с плавающей точкой это неожиданно оказалось трудной задачей. Тип double использует для хранения числовых значений 64 бита, однако некоторые процессоры применяют 80-разрядные регистры с плавающей точкой. Эти регистры обеспечивают дополнительную точность на промежуточных этапах вычисления, т.е. промежуточный результат вычислений храниться в 80-разрядном регистре, после чего ответ округляется до 64 бит. Однако этот результат может оказаться иным, если в процессе всех вычислений используется 64-разрядный процессор. По этой причине в первоначальном описании JVM указывалось, что все промежуточные вычисления должны округляться. Это вызвало протест многих специалистов, поскольку подобное округление не только может привести к переполнению, но и сами вычисления происходят медленнее. Это привело к тому, что в JDK 1.2 появилась поддержка ключевого слова strictfp, гарантирующая воспроизводимость результатов всех вычислений, производимых внутри этого метода, класса или интерфейса (вернее его реализации). Иными словами, ключевое слово strictfp гарантирует, что на каждой платформе вычисления с плавающей точкой будут вести себя одинаково и с определенной точностью, даже если некоторые платформы могут производить вычисления с большей точностью. Интересно, что для процессоров семейства x86 модуль операций с плавающей точкой был выделен в отдельную микросхему, называемую математическим сопроцессором (floating point unit (FPU)). Начиная с процессоров Pentium модели MMX модуль операций с плавающей точкой интегрирован в центральный процессор. Подробнее.

Далее. Стандарт IEEE 754 говорит нам, что представление действительных чисел должно записываться в экспоненциальном виде. Это значит, что часть битов кодирует собой так называемую мантиссу числа, другая часть — показатель порядка (степени), и ещё один бит используется для указания знака числа (0 — если число положительное, 1 — если число отрицательное). Математически это записывается так:
(-1)^s × M × 2^E, где s — знак, M — мантисса, а E — экспонента. Экспонента записывается со сдвигом, который можно получить по формуле, приведенной выше.

Что такое мантисса и экспонента? Мантисса – это целое число фиксированной длины, которое представляет старшие разряды действительного числа. Допустим наша мантисса состоит из четырех бит (|M|=4). Возьмем, например, число «9», которое в двоичной системе будет равно 1001.
Экспонента (ее еще называют «порядком» или «показателем степени») – это степень базы (двойки) старшего разряда. Можно рассматривать ее как количество цифр перед точкой, отделяющей дробную часть числа. Если экспонента переменная, записываемая в регистр и неизвестная при компиляции, то число называют «числом с плавающей точкой». Если экспонента известна заранее, то число называют «числом с фиксированной точкой». Числа с фиксированной точкой могут записываться в обыкновенные целочисленные переменные (регистры) путем сохранения только мантиссы. В случае же записи чисел с плавающей точкой, записываются и мантиса и экспонента в так называемом стандартном виде, например «1.001e+3». Сразу видно, что мантисса состоит из четырех знаков, а экспонента равна трем.

Допустим мы хотим получить дробное число, используя те же 3 бита мантиссы. Мы можем это сделать, если возьмем, скажем, E=1. Тогда наше число будет равно

1.001e+1 = 1×2^2 + 0×2^1 + 0×2^0 + 1×2^(-1) = 4 + 0,5 = 4,5

Одной из проблем такого подхода может стать различное представление одного и того же числа в рамках одной длины мантиссы. Нашу «9-ку», при длине мантиссы равной 5, можно представить и как 1.00100e+3 и как 0.10010e+4 и как 0.01001e+5. Это не удобно для оборудования, т.к. нужно учитывать множественность представления при сравнении чисел и при выполнении над ними арифметических операций. Кроме того, это не экономично, поскольку число представлений — конечное, а повторения уменьшают множество чисел, которые вообще могут быть представлены. Однако тут есть маленькая хитрость. Оказывается, что для вычисления значения первого бита можно использовать экспоненту. Если все биты экспоненты равны 0, то первый бит мантиссы также считается равным нулю, в противном случае он равен единице. Числа с плавающей точкой, в которых первый бит мантиссы равен единице, являются нормализованными. Числа с плавающей точкой, первый бит мантиссы в которых равен нулю, называются денормализованными. С их помощью можно представлять значительно меньшие величины. Поскольку первый бит всегда может быть вычислен, нет необходимости хранить его явным образом. Это экономит один бит, так как неявную единицу не нужно хранить в памяти, и обеспечивает уникальность представления числа. В нашем примере с «9» нормализованным представлением будет 1.00100e+3, а мантисса будет храниться в памяти как «00100», т.к. старшая единица подразумевается неявно. Проблемой такого подхода является невозможность представления нуля, о которой я скажу чуть позже. Подробнее об этом и многом другом можно почитать тут и тут.

К слову, в JDK 1.5 допустимо задавать числа с плавающей точкой в шестнадцатеричном формате. Например, 0.125 можно представить как 0x1.0p-3. В шестнадцатеричной записи для указания экспоненты используется знак «p» вместо «е».

Вещи, о которых стоит помнить, работая с Double:

  1. Целочисленное деление на 0 генерирует исключение, в то время как результатом деления на 0 чисел с плавающей точкой является бесконечность (или NaN в случае деления 0.0/0). Кстати мне было интересно узнать, что разработчики JVM, согласно все тому же стандарту IEEE 754 ввели также и значения Double.NEGATIVE_INFINITY и Double.POSITIVE_INFINITY, равные -1.0 / 0.0 и 1.0 / 0.0 соответственно.
  2. Double.MIN_VALUE на самом деле не самое маленькое число, которое можно записать в double. Помните, мы говорили о том, что согласно стандарту IEEE 754, старшая единица мантиссы указывается неявно? Так вот. Как уже было оговорено выше, в нормализованной форме числа с плавающей точкой невозможно представить ноль, поскольку нет такой степени двойки, которая равнялась бы нулю. И разработчики JVM специально для решения этой проблемы ввели переменную Double.MIN_VALUE, которая, по сути, является максимально близким значением к нулю. Самым маленьким значением, которое вы можете сохранить в double является «-Double.MAX_VALUE».
    System.out.println(0.0 > Double.MIN_VALUE); // возвращает false 
  3. Развивая предыдущую тему, можно привести еще один интересный пример, показывающий нам, что не все так очевидно, как может показаться на первый взгляд. Double.MAX_VALUE возвращает нам 1.7976931348623157E308, но что будет если мы преобразуем строку, содержащую число с плавающей запятой в double?
    System.out.println(Double.parseDouble("1.7976931348623157E308")); // (...7E308) = 1.7976931348623157E308 max value 
    System.out.println(Double.parseDouble("1.7976931348623158E308")); // (...8E308) = 1.7976931348623157E308 same???
    System.out.println(Double.parseDouble("1.7976931348623159E308")); // (...9E308) = Infinity
    

    Оказывается, между Double.MAX_VALUE и Double.POSITIVE_INFINITY есть еще некоторые значения, которые при вычислении округляются в одну или другую сторону. Тут стоит остановиться подробнее.

    Множество вещественных чисел является бесконечно плотным (dense). Не существует такого понятия, как следующее вещественное число. Для любых двух вещественных чисел существует вещественное число в промежутке между ними. Это свойство не выполняется для чисел с плавающей точкой. Для каждого числа типа float или double существует следующее число. Кроме того, существует минимальное конечное расстояние между двумя последовательными числами типа float или double. Метод Math.nextUp() возвращает следующее число с плавающей точкой, превышающее заданный параметр. Например, данный код печатает все числа типа float между 1.0 и 2.0 включительно.

    float x = 1.0F;
    int numFloats = 0;
    while (x <= 2.0) {
        numFloats++;
        System.out.println(x);
        x = Math.nextUp(x);
    }
    System.out.println(numFloats);
    

    Оказывается, что в промежутке от 1.0 до 2.0 включительно лежит ровно 8,388,609 чисел типа float. Это немало, но намного меньше, чем бесконечное множество вещественных чисел, которые находятся в том же диапазоне. Каждая пара последовательных чисел типа float находится на расстоянии примерно 0.0000001 друг от друга. Это расстояние называется единицей наименьшей точности (unit of least precision – ULP). Для типа double ситуация совершенно идентичная, за исключением того факта, что кол-во чисел после запятой значительно выше.

Пожалуй, на этом все. Желающим «копнуть поглубже» может пригодится следующий код:

// Возвращает представление заданного значения с плавающей точкой в соответствии с IEEE 754
long lbits = Double.doubleToLongBits(-0.06);
long lsign = lbits >>> 63; // знак
long lexp = (lbits >>> 52 & ((1 << 11) - 1)) - ((1 << 10) - 1); // порядок
long lmantissa = lbits & ((1L << 52) - 1); // мантисса
System.out.println(lsign + " " + lexp + " " + lmantissa);
System.out.println(Double.longBitsToDouble((lsign << 63) | (lexp + ((1 << 10) - 1)) << 52 | lmantissa));

Спасибо всем осилившим. Буду рад конструктивной критике и дополнениям.

Материалы по теме:
Новые математические возможности Java: Часть 2. Числа с плавающей точкой
IEEE Standard 754 Floating Point Numbers
Java Language and Virtual Machine Specifications
Представление вещественных чисел
Что нужно знать про арифметику с плавающей запятой
Арифметические операции над числами с плавающей точкой

Понравилась статья? Поделить с друзьями:
  • Error delphi32 dro
  • Error delivering перевод
  • Error deleting subkey clsid under msxml
  • Error deleting record
  • Error deleting partition ubuntu