Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.07.2012, 20:13   #1
Dimanduc
Пользователь
 
Регистрация: 25.02.2009
Сообщений: 40
По умолчанию странная вещь

Написал программу вывода денег по введенному числу. Например, вводится число 15.46 и должно вывестись 15 рублей 46 копеек. Код программы вот:
Код:
#include <stdio.h>
#include <conio.h>
#include <iostream>
using std::cout;

int main()
{
		float sh;
		long rub, kop;
		printf("Preobrazovanie shisla v deneshnii format\n");
		printf("Vvedite drobnoe shislo\n -> ");
		scanf("%f",&sh);
		rub=sh;
		kop=(sh-rub)*100;
		printf("%3.2f rub. iuto %i rub. %i kop.",sh,rub,kop);
		_getch();
}
Но почему то при выводе копеек теряется единица то есть вместо 25 рублей 45 копеек выводится 25 рублей 44 копейки. Почему так происходит?
Dimanduc вне форума Ответить с цитированием
Старый 26.07.2012, 20:26   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Визуал Студия 2010
Результат:
Цитата:
Preobrazovanie shisla v deneshnii format
Vvedite drobnoe shislo
-> 25.45
25.45 rub. iuto 25 rub. 45 kop.
Не вижу боков.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 26.07.2012, 21:26   #3
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Данные хранятся в двоичном виде, и не всегда удается установить абсолютно точное соответствие с десятичным. Если, скажем, с 0.75 проблем нет: 0.75(10) = 1*0.5 + 1*(0.5)^2 = 0.11(2), то многие другие числа удается привести в двоичный вид только приближенно. Так что вместо 25.45 в памяти вполне может храниться что-то вроде 25.4499999... и при округлении (отбрасывании дробной части) эти 0.99999... копеек потеряются.

В принципе если поменять float на double (у него точность выше), то проблема обычно решается.

И еще, по поводу вашего кода. Если уж используете стандартную библиотеку (std::cout), то совсем не нужно пользоваться сишными функциями (printf, scanf), их можно заменить стандартными потоками. Кроме того, если нет особой необходимости, то лучше использовать для всех целых чисел тип int, а для дробных - double. Плюс вместо getch опять же посоветую вариант из стандарта C++
Код:
std::cin.ignore();
std::cin.get();
P.S. И еще. Я бы вам настоятельно посоветовал использовать названия топиков, которые отражали бы суть вашего вопроса/проблемы. Например, "ошибка округления". А если компилятор выдает вам ошибку (как в предыдущих ваших темах), то гораздо быстрее и полезнее лично вам вбить номер и описание этой ошибки в гугль. Все ошибки уже не раз обсуждались на просторах сети, возможные варианты ее возникновения обычно приводятся. Читайте, сравнивайте со своим кодом, учитесь понимать, что значит каждая ошибка. Со временем это вам пригодится.
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же

Последний раз редактировалось Гром; 26.07.2012 в 21:36.
Гром вне форума Ответить с цитированием
Старый 27.07.2012, 01:39   #4
asmars
Форумчанин
 
Аватар для asmars
 
Регистрация: 28.05.2011
Сообщений: 309
По умолчанию

Цитата:
Плюс вместо getch опять же посоветую вариант из стандарта C++
А какая разница ?
Чем Ваш вариант лучше?
Спеши медленно.
asmars вне форума Ответить с цитированием
Старый 27.07.2012, 12:43   #5
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Тем, что getch, как и вся conio не является POSIX-совместимой, не входит в стандарты ни Си, ни C++ и, к примеру, на Linux придется обходиться без нее. А с cin таких проблем нет в принципе, это стандарт, и он работает везде.
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 27.07.2012, 14:24   #6
Dimanduc
Пользователь
 
Регистрация: 25.02.2009
Сообщений: 40
По умолчанию

Спасибо за объяснение проблемы и советы. Советы учту обязательно. Хочется узнать еще, а как же именно формально использовать вместо getch то что вы написали в коде:
Код:
std::cin.ignore();
std::cin.get();
Просто вместо getch вбить?
И еще: функцию printf я использовал для корректировки вывода числа: не 567.4434234234342, а 567.44 допустим. Если не использовать функцию printf то каким образом это можно сделать?

Последний раз редактировалось Dimanduc; 27.07.2012 в 14:40.
Dimanduc вне форума Ответить с цитированием
Старый 27.07.2012, 15:54   #7
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Да, просто вбить вместо нее. ignore нужен на случай, если в потоке ввода осталось что-то еще не считанное (например, вы ввели в окне два числа, нажали Enter, а в коде был только один cin >> i - одно число считалось, другое осталось висеть в потоке), get - непосредственно дожидается ввода чего-то еще (фактически - необязательный ввод с обязательным нажатием клавиши Enter), после чего программа завершается.

Вместо printf можно использовать манипуляторы, в частности для вывода с определенной точностью - setprecision. Также поищите информацию о других манипуляторах ввода/вывода (например, Б. Страуструп "Язык программирования C++, специальное издание", глава 21.4.6).
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 27.07.2012, 20:29   #8
Dimanduc
Пользователь
 
Регистрация: 25.02.2009
Сообщений: 40
По умолчанию

Цитата:
Вместо printf можно использовать манипуляторы, в частности для вывода с определенной точностью - setprecision. Также поищите информацию о других манипуляторах ввода/вывода (например, Б. Страуструп "Язык программирования C++, специальное издание", глава 21.4.6)
setprecision попробовал использовать - не получилось, компилятор его не "видит". Если я правильно понимаю его нужно использовать с заголовочным файлом iomanip.h, но даже этот файл не определяется. Я не знаю что делать... Прочитал то, что вы посоветовали - я там ничего толком не понял и информации нужной не нашел...
Dimanduc вне форума Ответить с цитированием
Старый 27.07.2012, 20:55   #9
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Не iomanip.h, а просто iomanip. Подключение частей стандартной библиотеки с .h - устаревший способ, компилятор вполне может его не поддерживать.

Такой код у меня выводит, как и положено, 25.45
Код:
#include <iostream>
#include <iomanip>

int main()
{
double Price = 25.450001;
std::cout << std::setprecision(2) << std::fixed << Price;

std::cin.ignore();
std::cin.get();
}
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 27.07.2012, 23:04   #10
Dimanduc
Пользователь
 
Регистрация: 25.02.2009
Сообщений: 40
По умолчанию

У меня вывод нестабильный. То верно выводит то неверно, но возможно это связано с версией скачанной с неофициального сайта.
Dimanduc вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
непонятная вещь Dimanduc Общие вопросы C/C++ 41 27.07.2012 14:58
Непонятная вещь Doem HTML и CSS 3 31.03.2011 03:07
Рассчитаем незамысловатую вещь) Владимир_Мар Общие вопросы Delphi 1 04.06.2010 18:31
Как сделать такую вещь? Mr.Qwerty Общие вопросы Delphi 9 01.08.2009 05:17