Я новичок в программировании. Мне нужна была простая функция для преобразования любого числа с десятичной точкой X.YZ в XYZ. Я сделал это, умножив его в 10 раз и используя двойной в ИНТ преобразование.
int main()
{
std::cout << "Number: " << std::endl;
double a;
// the uninitialized b was pointed out, its not the issue
long b = 0;
std::cin >> a;
while(b!=a)
{
a*=10;
b=a;
}
std::cout << a << std::endl;
return 0;
}
Это работает как 90 процентов времени. Для некоторых чисел, таких как 132,54, программа работает бесконечно долго. Он обрабатывает 132.547 (который должен использовать больше памяти, чем 132.54) так, как должен.
Итак, мой вопрос: почему он не работает на 100 процентов для чисел в диапазоне памяти long int? Почему 132.54 и похожие цифры?
Я использую Codeblocks и компилятор GNU GCC.
Многие десятичные числа с плавающей запятой не могут быть точно представлены в двоичном виде. Вы получаете только близкое приближение.
Если 132,54 представлен как 132,539999999999999, вы никогда не получите совпадение.
Напечатайте значения в цикле, и вы увидите, что произойдет.
Проблема в том, что большинство десятичных значений не могут быть представлены точно как значения с плавающей точкой. Таким образом, наличие десятичного значения, которое имеет только пару цифр, не гарантирует, что умножение на десять достаточных раз приведет к получению значения с плавающей запятой без дробной части. Чтобы увидеть это, отобразите значение a
каждый раз через цикл. В младших битах много шума.
Ваша проблема в том, что вы никогда не инициализируете b
и, следовательно, есть неопределенное поведение.
Вы должны сделать это:
long b = 0;
Теперь вы можете сравнить b с чем-то другим и получить хорошее поведение.
Также сравнивая float
с integral
type должен быть выполнен как сравнение с соответствующим значением epsilon:
while(fabs(an_int - a_float) < eps)
Вместо того, чтобы читать это как двойное, читайте это как строку и анализируйте это. Таким образом, вы не столкнетесь с проблемой плавающей точности.
long b;
Вот ты определять b
, С этого момента переменная содержит значение мусора. Значение может быть абсолютно случайным, в основном это то, что было в памяти, когда оно было выделено. После этого вы используете эту переменную в условии:
while(b!=a)
Это приведет к неопределенное поведение, что в основном означает, что может произойти все что угодно, включая возможность того, что приложение будет работать (если вам повезет), в зависимости от значения мусора, которое находится в b
,
Чтобы избежать этого, вам нужно будет инициализировать b
с некоторым значением, например, long b = 0
,