Как мне правильно использовать setprecision(), чтобы добавить .00 в конец суммы денег?

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

void TollBooth::arrive(Car c)
{
  carcount += 1;
  int cost;
  int doors = c.getDoors();
  cost = 3 + doors;
  total+=cost;
  cout << setw(12) << left << "Car: "<< setw(8) <<c.getID()<< setw(8) 
    << "  Amount Due: $ " << setw(5) << fixed << right << setprecision(2) << cost << endl;
}

Однако выводится «стоимость» без завершающих нулей.


person Lars Dunson    schedule 19.04.2016    source источник
comment
Связанный: stackoverflow.com/questions/2519645 /   -  person πάντα ῥεῖ    schedule 19.04.2016
comment
Еще больше связано, если не обман: сбивает с толку   -  person πάντα ῥεῖ    schedule 19.04.2016
comment
std::setprecision устанавливает количество всех цифр. должны быть показаны не только те, которые следуют после запятой.   -  person πάντα ῥεῖ    schedule 19.04.2016
comment
@πάντα ῥεῖ Я думаю, что это позволяет вам указать количество цифр после запятой, когда вы используете его с фиксированным манипулятором ios.   -  person Biruk Abebe    schedule 19.04.2016
comment
@bkVnet Да, ты прав.   -  person πάντα ῥεῖ    schedule 19.04.2016


Ответы (4)


Не используйте setprecision, просто отобразите завершающий .00 напрямую (и откорректируйте предшествующий setw):

void TollBooth::arrive(Car c)
{
    carcount += 1;
    int doors = c.getDoors();
    int cost = 3 + doors;
    total += cost;
    cout << setw(12) << left << "Car: "<< setw(8) <<c.getID()<< setw(8) << "  Amount Due: $ " 
    << setw(3) << right << cost << ".00" << endl;
}

Вы можете привести к плавающей запятой, а для значения int использование double должно быть безопасным на всех известных мне архитектурах. Однако не применяйте к float; как я отметил в комментарии, 32-битные числа с плавающей запятой IEEE не обладают точностью, чтобы представить весь диапазон int (например, (1 << 24) + 1 становится равным 1 << 24 при приведении к 32-битному IEEE float). Лучше всего избегать риска ошибки точности, когда в этом нет необходимости.

person ShadowRanger    schedule 19.04.2016

В вашем конкретном случае это не добавляет конечные нули, потому что cost объявлено как integer в вашем коде. Вам нужно привести его к double или float (хотя это может привести к потере данных для некоторых целочисленных значений).

cout << setw(12) << left << "Car: "<< setw(8) <<c.getID()<< setw(8) << "  Amount Due: $ " 
<< setw(5) << fixed << right << setprecision(2) << static_cast<double>cost << endl;

Кстати, вы можете прочитать ссылки, указанные в разделе комментариев вашего вопроса.

person Biruk Abebe    schedule 19.04.2016
comment
@bkVnet _ _хотя я не вижу смысла делать цену (денежную стоимость) целым числом. Хорошо, проверьте ссылку из моего первого комментария. - person πάντα ῥεῖ; 19.04.2016
comment
@ πάντα ῥεῖ Точка очень принята. Спасибо. - person Biruk Abebe; 19.04.2016
comment
@bkVnet: Даже если вы хотите думать о деньгах как о нецелых числах, использование значений с плавающей запятой для хранения денег — верный путь к катастрофе. Фиксированная точка - гораздо лучшая идея, которая в любом случае представлена ​​​​целым числом (то есть просто выражается в центах). - person AnT; 19.04.2016
comment
@bkVnet: я бы настоятельно рекомендовал double вместо float здесь, если вы должны использовать плавающую точку. 32-битный IEEE float имеет достаточно ограниченную точность, поэтому вы начинаете терять данные даже при целочисленных преобразованиях около 25-битной отметки, которая находится внутри диапазона int (в быстром тесте на Python ctypes.c_float(16777217).value дает вам 16777216.0). - person ShadowRanger; 19.04.2016
comment
@ShadowRanger Ты прав. Я обновлю ответ. - person Biruk Abebe; 19.04.2016

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

Однако вернемся к вашей реальной проблеме: если вы хотите отформатировать денежные значения, вы, вероятно, захотите использовать std::put_money в любом случае вместо простого форматирования с плавающей запятой.

person MikeMB    schedule 19.04.2016

Вы можете использовать setprecision и showpoint:

double a = 14;
cout << setprecision(4) << showpoint << a;

Выход:

14.00

Недостатком является то, что вам придется вычислять аргумент setprecision.

person Andreas DM    schedule 19.04.2016