2010-11-15 3 views
1

Можно создать дубликат:
How do I fix this Perl code so that 1.1 + 2.2 == 3.3?вопросы сравнения Поплавок в Perl

Я работаю над сценарием Perl, который сравнивает строки, представляющие модели генных и печатает резюме сравнения. Если модели генов соответствуют друг другу, я распечатываю очень краткое резюме, но если они разные, то резюме довольно многословно.

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

Поскольку значение является числовым (поплавок), я использовал оператор == для сравнения.

if($stats->{overall_simple_matching_coefficient} == 1) 
{ 
    print "Gene structures match perfectly!\n"; 
} 

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

Я думал, что == был для численного сравнения и eq был для сравнения строк. Я что-то упустил?

Update: Если я распечатать значение перед сравнением ...

printf("Test: '%f', '%d', '%s'\n", $stats->{overall_simple_matching_coefficient}, $stats->{overall_simple_matching_coefficient}, $stats->{overall_simple_matching_coefficient}); 

... Я получаю это.

Test: '1.000000', '0', '1' 
+0

Что вы получаете, если вы печатаете значение '$ stats -> {general_simple_matching_coefficient}' непосредственно перед сравнением? –

+0

О, я на самом деле делал это раньше. Спасибо, я все это подниму. –

+0

Не уверен в perl, не используйте его так много, но в bash хотя бы '==' для строк и '-eq' для численных ... –

ответ

9

Первое, что любой учитель информатики языка должен научить вас о любом компьютерном языке, что YOU CANNOT COMPARE FLOATS FOR EQUALIT Y. Это верно для любого языка. Арифметика с плавающей точкой не является точной, и два поплавка, которые выглядят одинаково, будут отличаться от незначительных цифр где-то, где вы не можете их увидеть. Вместо этого, вы только можете сравнить, что они близко друг к другу - как

if (abs(stats->{overall_simple_matching_coefficient)-1) < 0.0001) 
+0

Спасибо за подсказку. Трудная часть для меня определяла толерантность/специфичность, в которой я нуждаюсь, потому что для длинных генов значение 0.9999 может быть действительным и отличным от значения 1.0000.Однако, хотя я, хотя и немного больше об этом, требуется толерантность, это всего лишь функция длины гена (которая является целочисленным значением). Если ген имеет длину 100, то требуется толерантность 0,01. Если он имел длину 1000, мне нужно .001 и так далее. –

+0

Но это еще не отвечает на мой вопрос о '==' vs 'eq'. Почему 'eq' работал, когда' == 'не сделал? –

+3

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

3

Что вы получите, если вы печатаете значение $stats->{overall_simple_matching_coefficient} только перед сравнением? Если это 1, попробуйте printf в формате "%20.10f". Я сильно подозреваю, что у вас есть ошибка округления (менее 1е-6), накопленная в переменной, и она не сравнивается с численными. Однако при преобразовании в строку, так как ошибка имеет право на 6-ое десятичное место, а формат строки по умолчанию - на шесть мест, он сравнивается с равным.

+0

Спасибо, что помогли мне визуализировать проблему! –

Смежные вопросы