Сравнение IEEE плавает и удваивается для равенства

Кажется, что синтаксически более простой способ и, следовательно, легче запомнить, в отличие от предлагаемых решений. Я предполагаю, что столбец называется «мета» в dataframe df:

df2 = pd.DataFrame(df['meta'].str.split().values.tolist())
9
задан Craig H 21 August 2008 в 21:47
поделиться

14 ответов

Лучший подход я думаю, должен сравнить ULPs.

bool is_nan(float f)
{
    return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) == 0x7f800000 && (*reinterpret_cast<unsigned __int32*>(&f) & 0x007fffff) != 0;
}

bool is_finite(float f)
{
    return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) != 0x7f800000;
}

// if this symbol is defined, NaNs are never equal to anything (as is normal in IEEE floating point)
// if this symbol is not defined, NaNs are hugely different from regular numbers, but might be equal to each other
#define UNEQUAL_NANS 1
// if this symbol is defined, infinites are never equal to finite numbers (as they're unimaginably greater)
// if this symbol is not defined, infinities are 1 ULP away from +/- FLT_MAX
#define INFINITE_INFINITIES 1

// test whether two IEEE floats are within a specified number of representable values of each other
// This depends on the fact that IEEE floats are properly ordered when treated as signed magnitude integers
bool equal_float(float lhs, float rhs, unsigned __int32 max_ulp_difference)
{
#ifdef UNEQUAL_NANS
    if(is_nan(lhs) || is_nan(rhs))
    {
        return false;
    }
#endif
#ifdef INFINITE_INFINITIES
    if((is_finite(lhs) && !is_finite(rhs)) || (!is_finite(lhs) && is_finite(rhs)))
    {
        return false;
    }
#endif
    signed __int32 left(*reinterpret_cast<signed __int32*>(&lhs));
    // transform signed magnitude ints into 2s complement signed ints
    if(left < 0)
    {
        left = 0x80000000 - left;
    }
    signed __int32 right(*reinterpret_cast<signed __int32*>(&rhs));
    // transform signed magnitude ints into 2s complement signed ints
    if(right < 0)
    {
        right = 0x80000000 - right;
    }
    if(static_cast<unsigned __int32>(std::abs(left - right)) <= max_ulp_difference)
    {
        return true;
    }
    return false;
}

Подобная техника может использоваться для, удваивается. Прием должен преобразовать плавания так, чтобы им заказали (как будто целые числа), и затем просто посмотрите, насколько отличающийся они.

Я понятия не имею, почему эта проклятая вещь завинчивает мои символы нижнего подчеркивания.Править: О, возможно, это - просто артефакт предварительного просмотра. Это в порядке затем.

7
ответ дан 4 December 2019 в 19:37
поделиться

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

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

0
ответ дан 4 December 2019 в 19:37
поделиться

Боже мой лорд не интерпретируйте биты плавающие как ints, если Вы не работаете на P6 или ранее.

0
ответ дан 4 December 2019 в 19:37
поделиться

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

Возможно, я должен объяснить проблему лучше. В C++, следующем коде:

#include <iostream>

using namespace std;


int main()
{
  float a = 1.0;
  float b = 0.0;

  for(int i=0;i<10;++i)
  {
    b+=0.1;
  }

  if(a != b)
  {
    cout << "Something is wrong" << endl;
  }

  return 1;
}

печатает фразу, "Что-то неправильно". Вы говорите, что это должно?

0
ответ дан 4 December 2019 в 19:37
поделиться

Интервал позволяет мне выразить значения ~10^9 (независимо от диапазона), который походит на достаточно для любой ситуации, где я заботился бы о приблизительно двух из них являющийся равным. И если это недостаточно, используйте 64-разрядную ОС, и Вы имеете о 10^19 отличные значения.

Я на самом деле поразил тот предел... Я пытался манипулировать временами в PS и время в тактах на моделировании, где Вы легко совершаете нападки 10^10 циклы. Независимо от того, что я сделал я очень быстро переполнил маленького диапазона 64-разрядных целых чисел... 10^19 не так, как Вы думаете, что это, дай мне 128 битов, вычисляющих теперь!

Плавания позволили мне получать решение математических проблем как значения, переполненные с нулями партий на нижнем уровне. Таким образом, у Вас в основном была десятичная точка, плавающая aronud в числе без потери точности (мне могло понравиться с более ограниченным отличным количеством значений, позволенных в мантиссе плавания по сравнению с 64-разрядным интервалом, но отчаянно необходимом диапазоне th!).

И затем вещи, преобразованные назад в целые числа для сравнения и т.д.

Раздражающий, и в конце я фрагментировал всю попытку и просто полагался на плавания и <и> сделать работу. Не прекрасный, но работы для варианта использования предположен.

0
ответ дан 4 December 2019 в 19:37
поделиться

Это скорее зависит от того, что Вы делаете с ними. Тип фиксированной точки с тем же диапазоном как плавание IEEE был бы многими много раз медленнее (и много раз больше).

Хорошо, но если я хочу бесконечно мало небольшое битовое разрешение затем, оно вернулось к моей исходной точке: == и! = не имейте никакого значения в контексте такой проблемы.

Интервал позволяет мне выразить значения ~10^9 (независимо от диапазона), который походит на достаточно для любой ситуации, где я заботился бы о приблизительно двух из них являющийся равным. И если это недостаточно, используйте 64-разрядную ОС, и Вы имеете о 10^19 отличные значения.

Я могу выразить, оценивает диапазон 0 к 10^200 (например), в интервале, это - просто битовое разрешение, которое страдает (разрешение было бы больше, чем 1, но, снова, никакое приложение не имеет такой диапазон, а также такое разрешение).

Подводя итоги, я думаю во всех случаях один, любой представляет континуум значений, в этом случае! = и == не важны, или каждый представляет фиксированное множество значений, которое может быть отображено на интервале (или другой тип фиксированной точности).

0
ответ дан 4 December 2019 в 19:37
поделиться

@DrPizza: Я не гуру производительности, но я ожидал бы, что операции фиксированной точки будут более быстрыми, чем операции с плавающей точкой (в большинстве случаев).

@Craig H:Конечно. я полностью хорошо с ним печатающий это. Если a или b хранят деньги затем, они должны быть представлены в фиксированной точке. Я изо всех сил пытаюсь думать о примере реального мира, где такая логика должна быть объединена с плаваниями. Вещи, подходящие для плаваний:

  • веса
  • разряды
  • расстояния
  • значения реального мира (как от ADC)

Для всех этих вещей или Вы очень затем числа и просто представляют результаты пользователю для человеческой интерпретации, или Вы делаете сравнительный оператор (даже если такой оператор, "эта вещь в 0.001 из этой другой вещи"). Сравнительный оператор как мой только полезен в контексте алгоритма: "в 0,001" частях зависит, на каком физическом вопросе Вы задаете. То, что мои 0.02. Или я должен сказать 2/100ths?

0
ответ дан 4 December 2019 в 19:37
поделиться

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

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

0
ответ дан 4 December 2019 в 19:37
поделиться

Это, кажется, заботится о большинстве проблем путем объединения допуска относительной и абсолютной погрешности. Подход ULP лучше? Если так, почему?

ULPs являются прямой мерой "расстояния" между двумя числами с плавающей точкой. Это означает, что они не требуют, чтобы Вы вызвали в воображении значения относительной и абсолютной погрешности, и при этом Вы не должны удостоверяться, что получили те значения "о праве". С ULPs можно выразить непосредственно, как близко Вы хотите, чтобы числа были, и те же пороговые работы точно также для маленьких значений что касается больших.

0
ответ дан 4 December 2019 в 19:37
поделиться

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

Даже если мы делаем числовой анализ для уменьшения накопления ошибки, мы не можем устранить его, и нас можно оставить с результатами, которые должны быть идентичными (если бы мы вычисляли с реалами), но отличайтесь (потому что мы не можем вычислить с реалами).

0
ответ дан 4 December 2019 в 19:37
поделиться

@DrPizza: Я не гуру производительности, но я ожидал бы, что операции фиксированной точки будут более быстрыми, чем операции с плавающей точкой (в большинстве случаев).

Это скорее зависит от того, что Вы делаете с ними. Тип фиксированной точки с тем же диапазоном как плавание IEEE был бы многими много раз медленнее (и много раз больше).

Вещи, подходящие для плаваний:

3D графика, физика/разработка, моделирование, моделирование климата....

1
ответ дан 4 December 2019 в 19:37
поделиться

Боже мой лорд не интерпретируйте биты плавающие как ints, если Вы не работаете на P6 или ранее.

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

т.е. это - цена, которую стоит заплатить.

0
ответ дан 4 December 2019 в 19:37
поделиться

Текущая версия, которую я использую, является этим

bool is_equals(float A, float B,
               float maxRelativeError, float maxAbsoluteError)
{

  if (fabs(A - B) < maxAbsoluteError)
    return true;

  float relativeError;
  if (fabs(B) > fabs(A))
    relativeError = fabs((A - B) / B);
  else
    relativeError = fabs((A - B) / A);

  if (relativeError <= maxRelativeError)
    return true;

  return false;
}

Это, кажется, заботится о большинстве проблем путем объединения допуска относительной и абсолютной погрешности. Подход ULP лучше? Если так, почему?

3
ответ дан 4 December 2019 в 19:37
поделиться

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

0
ответ дан 4 December 2019 в 19:37
поделиться
Другие вопросы по тегам:

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