Для чого використовується суфікс `f` на плаваючому значенні


74

Мені цікаво, в чому різниця між цими двома змінними в C:

і

Яке використання суфікса fв цьому випадку?


1
Багато дублікатів, наприклад "f" після числа / плаваючого об'єкта-C / C
Paul R

Я можу рекомендувати вікторину з плаваючою комою як подальше читання.
Мартін Шаррер,

Відповіді:


74

3.00інтерпретується як a double, на відміну від 3.00fякого розглядається компілятором як a float.

fСуфікс просто повідомляє компілятор , який є floatі який є double.

Див. MSDN (C ++)


1
Отже, у прикладі OP два висловлювання еквівалентні, оскільки дубль у будь-якому випадку автоматично зрізається у поплавок?
Лінкольн Бергесон,

6
@LincolnBergeson: У випадку з ОП так. Однак, якщо ви отримаєте рівняння float price = 7.50 / 2.50;проти, float price = 7.50f / 2.50f;тоді результат може відрізнятися через різну роздільну здатність. У першому випадку компілятору доведеться провести обчислення, а doubleпотім перетворити результат на float. У другому випадку розрахунок проводиться в float. Зверніть увагу, що якщо є лише одне значення, doubleто все це обчислюється як double. Компілятору C не дозволяється оптимізувати це, оскільки їх округлення буде відрізнятися. Так floatvarA = floatvarB / 2.0працює гірше, ніж з 2.0f.
Мартін Шаррер,

35

На додаток до вже сказаного, відстеження 1,0 проти 1,0f є важливішим, ніж усвідомлюють багато людей. Якщо ви пишете такий код:

Тоді х буде підвищено до дубля, оскільки 2.0 - це дубль. Компілятору заборонено оптимізувати просування, інакше це порушить стандарт C. Обчислення відбувається з подвійною точністю, а потім результат неявно усікається у поплавок. Це означає, що обчислення буде повільнішим (хоча і точнішим), ніж це було б, якби ви написали 2.0f або 2.

Якби ви написали 2, константа мала би тип int, який був би підвищений до плаваючого, а обчислення було б зроблено з "точністю плаваючої". Хороший компілятор попереджав би вас про цю акцію.

Детальніше про правила "звичайного арифметичного перетворення" читайте тут:

http://msdn.microsoft.com/en-us/library/3t4w2bkb%28v=vs.80%29.aspx


3
Насправді, компілятор, вартий його солі, створить множення з однією точністю для вашого прикладу float y = x * 2.0;. Насправді компілятор, вартий його солі, генерує одноточне множення для float y = x * (double)0.1f;набагато вражаючого подвигу (але все ж правильної оптимізації).
Pascal Cuoq

@PascalCuoq: Такий компілятор порушить стандарт C. Ви прямо сказали йому робити doubleмноження, використовуючи, 2.0а не 2.0f. Компіляторам заборонено використовувати оптимізацію, яка змінила б числовий результат.
Мартін Шаррер,

1
@MartinScharrer Це не змінює числовий результат (повірте, у мене є золотий значок із плаваючою крапкою). Я також міг би зазначити, що Clang застосовує цю оптимізацію, але про плаваючу крапку Clang'c стільки нестандартного, що це нічого не доведе.
Паскаль Куок,

2
@MartinScharrer Довідка, яка не апелює до влади, написана Figueroa і містить у заголовку слова "подвійне округлення", але я не можу знайти її у версії, яка зараз не стоїть перед платформою. Це показує, що (float)((double)float_x * (double)float_y) == float_x * float_yрівність, яку компілятор застосовує навпаки для цієї оптимізації. Це працює, оскільки наближення 2 як doubleі floatоднакові.
Паскаль Куок,

16

Оскільки несуфіксовані літерали з плаваючою крапкою є подвійними, а округлення означає, що навіть малі літерали можуть приймати різні значення при округленні до плаваючої та подвійної. Це можна спостерігати на наступному прикладі:

Це виведе no, оскільки 0.67має інше значення при округленні до плаваючого, ніж при округленні до подвійного. З іншої сторони:

виходи yes.

Суфікс можна вказати, використовуючи великі або малі літери.

Спробуйте також це:

Перевірте @ codepade


Порівняння чисел із плаваючою комою з == - погана практика. Причиною цього є помилки, які накопичуються при перетворенні десяткової в двійкову. Ці помилки накопичуються, коли ви починаєте маніпулювати плаваючими числами, що робить неможливим точне порівняння. З цієї причини ніколи не слід розраховувати, що плаваюче число дорівнює чомусь точному.
Ignas2526,

@ Ignas2526, то що б ви запропонували, якщо я якийсь час увійду в необхідність порівняння плаваючих знаків. Чи можете ви дати мені вказівник, звідки читайте далі.
Grijesh Chauhan

2
Ось кілька сторінок, які розповідають про проблему, яку я згадав тут: docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Ignas2526

@ Ignas2526 дякую, я прочитаю це, якщо знайду що-небудь додати у свою відповідь, то оновлю. Ваше посилання буде корисним і для інших.
Grijesh Chauhan


0

Це тому, що за замовчуванням тип числового літералу з плаваючою комою - символи 3.00 подвійні, не плаваючі. Щоб зробити цю компіляцію, вам потрібно додати суфікс f (або F).


0

Додавши ще кілька комбінацій порівнянь між плаваючими та подвійними типами даних.

Вихід:


-1

Часто різниця не важлива, оскільки компілятор у будь-якому випадку перетворить подвійну константу в плаваючу. Однак враховуйте це:


1
Ваша відповідь не чітко пояснює різницю між 3.00 та 3.00f ...
Джеймс,

1
Точно ... Можливо, ви додаєте якусь інформацію, але не відповідаєте на питання ...
Джеймс,

1
Якщо ви спробуєте зберегти подвійну константу у плаваючу, тоді так, ви отримаєте неявну деградацію з подвійної на плаваючу. Але коли справа стосується виразів, компілятор не може перетворити подвійні константи у плаваючі, не порушуючи стандарт C / C ++. Якщо подвійна константа стоїть у тому самому виразі, що і float, тоді правила "звичайного арифметичного перетворення" в C / C ++ вимагають, щоб плаваючий явно підвищувався до double.
Лундін,

4
Крім того, чому ви відповідаєте на C ++, коли OP пише на C? Ваш приклад не має значення в C, оскільки C не має такої суворої перевірки типу, як C ++.
Лундін,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.