使用 4/5 舍入规则对数字进行舍入

Rounding numbers using the 4/5 rounding rule

我目前正在学习 C++。

I have to write a simple class Money that performs calculations involving dollars and cents where arithmetic has to be accurate to the last cent using the 4/5 rounding rule.

我以前从未处理过货币金额,所以我在理解如何从我的 class 中获得最大收益时遇到了一些麻烦。我知道我不应该用 float 表示货币金额。所以我为 class 使用了两个数据成员来分别存储美元和美分:

long int dollars
long int cents 

我的问题是我不知道何时以及如何舍入数字。当我尝试为此 class 实现输入运算符时,我问了自己这个问题。假设用户输入值:12.456, 45.999, 9.54

  1. 我应该在什么时候四舍五入这些数字?

  2. 是先在算术运算中使用,然后对结果进行四舍五入,还是在输入程序时直接四舍五入?

  1. 我能说的最好的就是将值作为字符串读取。此时您可以操作每个 item/number,因为字符串本质上是字符数组。

  2. 另一种选择是输入强制转换,例如

    浮动 x = 10.01; // x = 10.01

    (int) y = x; // y = 10

以浮点形式读取值并从那里分解它们。

希望对您有所帮助!

我建议将输入乘以 1000 左右,使输入成为一个整数,这样你对其进行的操作会更准确。四舍五入后,您可以使用整数除法计算美元,使用余数运算符计算美分(乘以 10)。至于你的第二个问题,你至少应该在四舍五入之前将数字转换成美元和美分的整数,然后你可以选择你喜欢的。以下是四舍五入输入的示例:

/* Note: Code untested */
double x;
std::cin >> x;    // x = 45.999
long y = x * 1000;        // y = 45999

int dollars = y / 1000;    // dollars = 45
int cents = y % 1000       // cents = 999 (divide by 10 to get real # of cents)

if (cents % 10 >= 5) {   // if last digit should be rounded up (true)
    cents += 10;            // add 10 (cents = 1009)
    cents -= (cents % 10);   // remove the last digit (cents = 1000)
} 
else if (cents % 10 < 5) {  // if last digit should be rounded down (false)
    cents -= (cents % 10);   // remove last digit
}

cents /= 10;        // make cents a factor of 100 instead of 1000 (cents = 100)

if (cents >= 100) {    // if cents more than  (true)
    dollars++;       // adjust dollars (dollars = 46)
    cents -= 100;     // remove 100 from cents (cents = 0)
}

// prints "Amount is .0"
std::cout << "Amount is $" << dollars << "." << cents << "\n";

至于类型转换,它们不是四舍五入的最佳选择。如果您要使用以下代码:

double x = 45.999;
int y = (int)x;

你会得到 y == 45 因为当将任何浮点类型转换为任何整数类型时,小数部分将被完全忽略。

希望对您有所帮助。

我建议您对 cents 执行操作,并仅使用舍入将金额打印到标准输出。

您可以使用 locale facet to parse monetary expressions and std::stringstream, along with stream manipulators 来指定精度,作为实现您想要的 class 的基础结构。

以下是美分和美元之间的换算示例:

int sum_in_cents = 10000;

// stringstream imbued with the local configuration
std::stringstream ss;
ss.imbue(std::locale(""));

// ss contains 0.00 (assuming a en_US locale configuration)
ss << std::showbase << std::put_money(sum_in_cents);

此外,还有 a boost library 货币格式。


注意:常规的4/5舍入是由标准库函数round()执行的。如果你想自己实现一些东西,你可以这样做:

double round (double n) 
{
    return (n > 0.0) ? floor(n + 0.5) : ceil(n - 0.5);
}

如果您想要四舍五入的整数结果,则不需要 ceil()floor():

int round (double i)
{
    return (i > 0.0) ? (i + 0.5) : (i - 0.5); 
}

拥有独立的美元和美分成员只会使代码变得不必要的复杂。只需使用美分,然后为 I/O.

重载算术和赋值运算符、构造函数以及可能的 << 和 >>

加法和减法很简单,在这种情况下只是正常的整数运算按比例缩放 100。一般定点division/multiplication需要重新缩放;在这种情况下你可以忽略它,因为用金钱除以或乘以金钱是没有意义的;但是,您可能希望重载货币乘以或除以整数和浮点类型(例如,用于税收、折扣或利息计算)。

通过为金钱重载 << 和 >> 运算符,您可以控制美分值的输入或显示方式 - 通过转换它 to/from dollars.cents.

在许多情况下可能需要舍入,但在大多数情况下这些可以通过运算符重载来处理。例如,以美元为单位的用户输入可以由赋值运算符和构造函数处理,而利息、税收或份额分配计算可能会产生几分之一的分数,可以通过重载 * 和 / 运算符来处理(尽管可能在内部使用赋值或构造函数,这样你只需要在一个地方四舍五入)。

保持以美分为单位的值并将浮点输入或中间美元值四舍五入为美分,使用 positive/negative 值处理可以按如下方式实现:

long long cents = static_cast<long long>((std::abs(dollars_fp) + 0.005) * 100) ;
if( dollars_fp < 0 )
{
    cents = -cents ;
}