Функция, чтобы определить, равны ли два количества почти при округлении к n значительным десятичным цифрам

Я не уверен, что точно понимаю ситуацию, но позвольте мне попытаться ответить.

Я бы рекомендовал выполнить двухэтапный процесс:

  1. Потоковая передача Spark сохраняет мини-пакеты во временную папку формата:

/yyy-mm-dd/.parquet

2019-02-06/100000.parquet, 2019-02-06/200000.parquet

  1. Другая искровая работа читает из соответствующего местоположения и выполняет агрегацию и фильтрацию времени.

Вы можете использовать библиотеку, подобную luigi , чтобы управлять ими.

35
задан Fermi paradox 5 August 2016 в 16:42
поделиться

8 ответов

Существует функция assert_approx_equal в numpy.testing (источник здесь) , который может быть хорошей начальной точкой.

def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True):
    """
    Raise an assertion if two items are not equal up to significant digits.

    .. note:: It is recommended to use one of `assert_allclose`,
              `assert_array_almost_equal_nulp` or `assert_array_max_ulp`
              instead of this function for more consistent floating point
              comparisons.

    Given two numbers, check that they are approximately equal.
    Approximately equal is defined as the number of significant digits
    that agree.
20
ответ дан 27 November 2019 в 06:33
поделиться

Вот взятие.

def nearly_equal(a,b,sig_fig=5):
    return ( a==b or 
             int(a*10**sig_fig) == int(b*10**sig_fig)
           )
8
ответ дан 27 November 2019 в 06:33
поделиться

Я полагаю, что Ваш вопрос не определяется достаточно хорошо, и модульные тесты, которые Вы представляете, доказывают его:

, Если приблизительно к десятичным разрядам фиги сигнала N Вы имеете в виду и десятичные разряды направо от десятичной точки', затем тест assert nearlyequal(1e9, 1e9 + 1 , 5) должен перестать работать, потому что, даже когда Вы раунд 1000000000 и 1000000001 с 0,00001 точностью, они все еще отличаются.

И если приблизительно к десятичным разрядам фиги сигнала N Вы имеете в виду 'Старшие значащие цифры N, независимо от десятичной точки', затем тест assert nearlyequal(-1e-9, 1e-9, 5) должен перестать работать, потому что 0.000000001 и-0.000000001 полностью отличаются при просмотре этот путь.

, Если Вы имели в виду первое определение, затем первый ответ на этой странице (Триптихом) хорош. Если Вы имели в виду второе определение, скажите это, я обещаю думать об этом :-)

5
ответ дан 27 November 2019 в 06:33
поделиться

Уже существует много больших ответов, но вот думание:

def closeness(a, b):
  """Returns measure of equality (for two floats), in unit
     of decimal significant figures."""
  if a == b:
    return float("infinity")
  difference = abs(a - b)
  avg = (a + b)/2
  return math.log10( avg / difference )


if closeness(1000, 1000.1) > 3:
  print "Joy!"
3
ответ дан 27 November 2019 в 06:33
поделиться

"Значащие цифры" в десятичном числе являются вопросом корректировки десятичной точки и усечения к целому числу.

>>> int(3.1415926 * 10**3)
3141
>>> int(1234567 * 10**-3)
1234
>>>
2
ответ дан 27 November 2019 в 06:33
поделиться

Это - довольно распространенная проблема с числами с плавающей точкой. Я решаю его на основе обсуждения в Разделе 1.5 из Demmel[1]. (1) Вычисляете ошибку округления. (2) Проверяете, что ошибка округления является меньше, чем некоторый эпсилон. Я не использовал Python в некоторое время и только имею версию 2.4.3, но я попытаюсь добраться, это исправляет.

Шаг 1. Ошибка округления

def roundoff_error(exact, approximate):
    return abs(approximate/exact - 1.0)

Шаг 2. Равенство с плавающей точкой

def float_equal(float1, float2, epsilon=2.0e-9):
    return (roundoff_error(float1, float2) < epsilon)

существует пара очевидных дефицитов с этим кодом.

  1. ошибка Деления на нуль, если точное значение является Нулем.
  2. не проверяет, что аргументами являются значения с плавающей точкой.

Пересмотр 1.

def roundoff_error(exact, approximate):
    if (exact == 0.0 or approximate == 0.0):
        return abs(exact + approximate)
    else:
        return abs(approximate/exact - 1.0)

def float_equal(float1, float2, epsilon=2.0e-9):
    if not isinstance(float1,float):
        raise TypeError,"First argument is not a float."
    elif not isinstance(float2,float):
        raise TypeError,"Second argument is not a float."
    else:
        return (roundoff_error(float1, float2) < epsilon)

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

На данном этапе единственная трудная вещь устанавливает правильное значение для эпсилона. Я заметил в документации для версии 2.6.1, что существует атрибут эпсилона в sys.float_info, таким образом, я использовал бы дважды что значение как эпсилон по умолчанию. Но правильное значение зависит и от Вашего приложения и от Вашего алгоритма.

[1] James W. Demmel, Прикладная Числовая Линейная алгебра , SIAM, 1997.

1
ответ дан 27 November 2019 в 06:33
поделиться

Oren Shemesh получил часть проблемы с проблемой, как указано, но существует больше:

утверждают nearlyequal (0.0, 1e-15, 5)

также сбои второе определение (и это - определение, которое я изучил в школе.)

, Неважно, то, сколько цифр Вы смотрите на, 0, не будет равняться не - нуль. Это могло оказаться головной болью для таких тестов, если у Вас есть случай, корректный ответ которого является нулем.

1
ответ дан 27 November 2019 в 06:33
поделиться

Есть интересное решение этой проблемы от Б. Доусона (с кодом C ++) в «Сравнение чисел с плавающей запятой» . Его подход основан на строгом представлении двух чисел IEEE и принудительном лексикографическом порядке, когда указанные числа представлены как целые числа без знака.

1
ответ дан 27 November 2019 в 06:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: