scanf float, print float, другое значение?

#include "stdafx.h"
#include "stdio.h"
#include "math.h"

int main()
{
float c;

printf("Type c");

scanf("%f", &c);


    printf("C is c: %f ",c);

    while(getchar()!='\n');
    getchar();
    return 0;

    }

Очень простой код, я только что начал с C. С большинством чисел работает нормально, но, например, если я ввожу 47.2, то он печатает мне 47.200001 с 88.4321 на выходе 88.432098, но с другими числами, такими как 5.4, работает нормально 5.400000 Я использую Microsoft Visual Studio 10.

Другое дело, если в приведенном выше коде вместо float c поставить double я не могу печатать f Что мне поставить вместо %f? Но меня больше беспокоит мой первый вопрос, может быть, это как-то связано с компилятором, может быть, я компилирую код C как C++, я не знаю.


person user1094566    schedule 14.12.2011    source источник
comment
@MichaelHaidl: Согласно стандарту, %f и %lf ведут себя одинаково при передаче в printf(), они отличаются только для scanf().   -  person Dietrich Epp    schedule 01.07.2016


Ответы (1)


Что касается точности ваших чисел. Это известная проблема при хранении значений с плавающей запятой в двоичном формате. Немного изменено из документации PHP...

Числа с плавающей запятой имеют ограниченную точность. Хотя это зависит от системы, большинство языков обычно используют формат двойной точности IEEE 754, который дает максимальную относительную ошибку из-за округления порядка 1.11e-16. Неэлементарные арифметические операции могут давать большие ошибки, и, конечно, при объединении нескольких операций необходимо учитывать распространение ошибки.

Кроме того, рациональные числа, которые точно представляются как числа с плавающей запятой по основанию 10, например 0,1 или 0,7, не имеют точного представления в виде чисел с плавающей запятой по основанию 2, которое используется внутри, независимо от размера мантиссы. Следовательно, их нельзя преобразовать во внутренние двоичные аналоги без небольшой потери точности. Это может привести к запутанным результатам: например, floor((0.1+0.7)*10) обычно возвращает 7 вместо ожидаемых 8, поскольку внутреннее представление будет примерно таким: 7,9999999999999991118....

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

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

person ahillman3    schedule 14.12.2011
comment
Если бы английский был моим основным языком, я бы интуитивно подумал о значении слова float, как-то я подумал, что оно будет выполнять арифметику с фиксированной пинтой en.wikipedia.org/wiki/Fixed-point_arithmetic. Спасибо, Ахиллман. - person user1094566; 15.12.2011
comment
поправьте меня, если я ошибаюсь, но не является ли это двойным (или десятичным на некоторых языках) более точным? - person Marnix v. R.; 15.12.2011