Находится непосредственно возможно реляционное сравнение между интервалом и плаванием в C?

Всегда делайте это с блоком try catch:

String versionName = "Version not found";

try {
    versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
    Log.i(TAG, "Version Name: " + versionName);
} catch (NameNotFoundException e) {
    // TODO Auto-generated catch block
    Log.e(TAG, "Exception Version Name: " + e.getLocalizedMessage());
}
8
задан Ciro Santilli 新疆改造中心法轮功六四事件 15 June 2015 в 16:00
поделиться

11 ответов

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

Проблема в том, что многие приращения, меньшие, чем целые числа, на самом деле не могут быть точно представлены в IEEE с плавающей запятой. Таким образом, если вы дойдете до числа с плавающей запятой, пытаясь «проиндексировать» его до значения 3,0 (скажем, с шагом 0,1), вполне возможно, что ваше сравнение на равенство никогда никогда не будет истинным.

Это также плохая идея только с точки зрения силы типов. Вы должны либо преобразовать float в int, либо проверить, что ваш int "достаточно близок" (например, <3.1 и> 2.9 или что-то вроде этого),

2
ответ дан 5 December 2019 в 05:03
поделиться

Я собираюсь немного изменить тенденцию. Что касается первого вопроса о достоверности сравнения, то ответ положительный. Это совершенно верно. Если вы хотите знать, точно ли значение с плавающей запятой равно 3, тогда сравнение с целым числом нормально. Целое число неявно преобразуется в значение с плавающей запятой для сравнения. Фактически, следующий код (по крайней мере, с компилятором, который я использовал) создавал идентичные инструкции сборки.

if ( 3 == f )
    printf( "equal\n" );

и

if ( 3.0 == f )
    printf( "equal\n" );

Так что это зависит от логики и какова намеченная цель. В синтаксисе нет ничего неправильного.

6
ответ дан 5 December 2019 в 05:03
поделиться

Это вообще (то есть всегда) плохая идея. Как вы и подозревали, сравнение от 3 до 30000001 действительно потерпит неудачу.

Что делает большинство людей, если сравнение int-float действительно необходимо, так это выбирают некоторый порог допуска и следуют ему, например:

int x = 3;
float y = 3.0;

// some code here

float difference = (float) x - y;
float tolerableDifference = 0.001;

if ((-tolerableDifference <= difference) && (difference <= tolerableDifference)) {
    // more code
}
14
ответ дан 5 December 2019 в 05:03
поделиться

В вашем конкретном примере будет выполнена команда «сделать что-нибудь безумное». 3.0 не будет 3.0000001 во время выполнения.

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

2
ответ дан 5 December 2019 в 05:03
поделиться

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

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

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

Единственным исключением из правила точного сравнения является проверка на ровно ноль. Совершенно законно и часто разумно проверять точный ноль перед делением или логарифмом, поскольку ответ хорошо определен для любого ненулевого значения. Конечно, при наличии правил IEEE и NaN вы можете позволить этому скользить и проверить на NaN или Inf позже.

5
ответ дан 5 December 2019 в 05:03
поделиться

Это страшно. (Интересно, что еще вы найдете.)

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

Вместо этого я мог бы предложить что-то вроде этого (проверка на абсолютную ошибку / разницу):

#define EPSILON 0.0001 
if (fabs((float)x - y) < EPSILON) { /* Do stuff. */ }

что является обычным подходом и может быть достаточным для ваших целей , если ваши значения x и y "хороши". Если вы действительно хотите углубиться в тему сравнения чисел с плавающей запятой, эта статья , вероятно, содержит больше информации, чем вы хотите. В нем говорится о методе epsilon:

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

2
ответ дан 5 December 2019 в 05:03
поделиться

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

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

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

2
ответ дан 5 December 2019 в 05:03
поделиться

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

1
ответ дан 5 December 2019 в 05:03
поделиться

Если код выглядит буквально как то, что вы опубликовали (без промежуточных вычислений), тогда возникает вопрос: 3.0 и (float) 3 (поскольку целое число автоматически преобразуется в число с плавающей запятой) то же самое. Я думаю, что в этом случае они гарантированно будут одинаковыми, потому что 3 точно может быть представлено как float .

Кроме того: И даже если целое число не может быть точно представлено как float (т.е. если оно действительно большой), я бы предположил, что в большинстве реализаций x.0 и (float) x будут одинаковыми, потому что как компилятор сгенерирует x.0 в первую очередь, если не сделать что-то вроде (float) x ? Однако я полагаю, что это не гарантируется стандартом.

1
ответ дан 5 December 2019 в 05:03
поделиться

Возможно, вас заинтересует лекция на конференции разработчиков игр Числовая устойчивость для геометрических вычислений (или EPSILON НЕ 0,00001!) . В нем подробно описывается выбор хороших значений порога / эпсилон для множества задач.

(+1 к упоминанию «Что должен знать каждый компьютерный ученый о плавающей запятой» в другом ответе)

1
ответ дан 5 December 2019 в 05:03
поделиться

Edit:

The right way is to use the epsilon method:

#include <math.h>
int x = 3;
int y = 3.0;
if (fabs((float) x - y) < 0.0001) { // Adjust the epsilon
  // Do stuff
}
-1
ответ дан 5 December 2019 в 05:03
поделиться
Другие вопросы по тегам:

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