Почему C дает мне другой ответ, чем мой калькулятор?

Я столкнулся со странной проблемой с этим кодом:

legibIndex = 206.385 - 84.6 * (countSylb / countWord) - 1.015 * (countWord / countSent);

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

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

Даже если я жестко запрограммирую числа, я не получу 80, хотя получаю, когда ввожу их в свой калькулятор точно так, как видно. Я не могу представить, что не так.

Вот уравнение, которое нам дали:

Index = 206.835 - 84.6 * (# syllables/# words) - 1.015 * (# words/# sentences)

Как вы можете видеть, я просто вставил свои переменные (которые содержат правильные значения. Для справки, значения: 55 слогов, 40 слов, 4 предложения, как указано инструктором. Значения, которые моя программа выдает при запуске, представляют собой Индекс разборчивости 112.

Я пропустил какие-то скобки или что? Я в тупике!


person Blackbinary    schedule 08.02.2010    source источник
comment
Index — это int, все остальные переменные — int. Это имеет смысл, потому что у вас не может быть 0,2 слога или 0,5 слова. Но даже если вы поместите 206.835-84.6*(55/40)-1.015*(40/4) в программу (например, жесткое кодирование, как я сказал), это не даст правильного ответа.   -  person Blackbinary    schedule 08.02.2010
comment
Да, как указал sparks и ответил Чарльз, это проблема округления, вызванная вашими типами данных. И я держу пари, в этом и был смысл задания. :-)   -  person T.J. Crowder    schedule 08.02.2010
comment
О, целочисленное деление, спасибо!   -  person Blackbinary    schedule 08.02.2010
comment
И нет, ТиДжей, задание было намного сложнее, это как бы легкая часть в довершение всего, ха-ха. Это одна из причин, по которой я расстраивался. Знал, что это что-то простое.   -  person Blackbinary    schedule 08.02.2010
comment
Если вы хотите увидеть причину выполнения int/int и посмотреть на результат, сделайте то же самое с числами с плавающей запятой. Я считаю, что gcc всегда будет округляться до 0, но я не уверен, является ли это выбором компилятора или он указан в спецификации.   -  person sclarson    schedule 08.02.2010
comment
Да, я знаю, почему это происходит, просто мне это не приходило в голову.   -  person Blackbinary    schedule 08.02.2010
comment
По этой причине любой достойный стандарт кодирования не позволит программисту писать составные выражения. Подумайте об идеальной ситуации: пошаговое выполнение кода по одной строке за раз для подтверждения хода вычислений. Ноль ошибок каждый раз.   -  person logout    schedule 08.02.2010


Ответы (8)


С самого начала, из имен (которые включают слово count), я бы предположил, что countSylb, countSent и countWord объявлены как целые числа, и поэтому ваши деления выполняют целочисленную арифметику, усекая десятичные части. . Приведите их к поплавкам, и это должно исправить это.

legibIndex = 206.385 - 84.6 * ((float)countSylb / ((float)countWord) - 
               1.015 * (((float)countWord / ((float)countSent);
person Charles Bretana    schedule 08.02.2010
comment
Приведение к double может дать лучшие результаты. Многие гуру языка C советуют использовать double, а не float. - person Thomas Matthews; 09.02.2010
comment
@ Томас, если вы знаете, почему это так, не могли бы вы уточнить? - person Charles Bretana; 09.02.2010
comment
Насколько я понимаю, математическая библиотека закодирована как двойная точность, а константы с плавающей запятой имеют тип double. Кроме того, double точность дает большую точность, чем float. float следует использовать только при нехватке памяти. - person Thomas Matthews; 09.02.2010

Вероятно, у вас есть проблема с типом данных, когда вы округляете, потому что int/int = int вместо float.

Если вы примените к float или объявите как float, это должно вам помочь.

person sclarson    schedule 08.02.2010

Работает здесь. Возможно, вы выполняете целочисленное деление вместо деления с плавающей запятой:

>>> def leg(syl, wor, sen):
...   return 206.835 - 84.6 * (float(syl) / wor) - 1.015 * (float(wor) / sen)
... 
>>> print leg(55, 40, 4)
80.36
person Ignacio Vazquez-Abrams    schedule 08.02.2010

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

person user268769    schedule 08.02.2010

Когда я запускаю это в Haskell, я получаю правильный ответ (80.36000000000001).

person Chris Eidhof    schedule 08.02.2010

Я думаю, проблема в том, что (# слогов/# слов) становится равным 1, если вы используете целочисленную арифметику. Если вы убедитесь, что выполняете вычисления с использованием арифметики с плавающей запятой (то есть # слогов/# слов = 1,375), вы должны получить правильный ответ.

person Michael Williamson    schedule 08.02.2010

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

person mike_b    schedule 08.02.2010

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

Изменить Нет, это не так; используя приоритет оператора C, я получаю 80,36. Я ожидаю, что sparks был прав (и первым не попал в точку), что это проблема с типом данных, и вы сталкиваетесь с преждевременным округлением.

person T.J. Crowder    schedule 08.02.2010