c++ - 实现银行家的舍入 C++
问题描述
所以本质上我正在写一本 C++ 书,其中一个练习是修改书中的一个示例以使用银行家的四舍五入。对于上下文,银行家的四舍五入是在分数美分中四舍五入到最接近的偶数。我已经尝试了几个小时来找出如何实现它,但没有任何东西对我有用。书中的代码如下所示。
// Ex. 5.31: DollarAmount.h
// DollarAmount class gets two parameter constructor
#include <string>
#include <cmath>
class DollarAmount {
public:
// initialize amount from an int64_t value
explicit DollarAmount(int64_t dollars, int64_t cents) : amount{dollars * 100 + cents} { }
// add right's amount to this object's amount
void add(DollarAmount right) {
// can access private data of other objects of the same class
amount += right.amount;
}
// subtract right's amount from this object's amount
void subtract(DollarAmount right) {
// can access private data of other objects of the same class
amount -= right.amount;
}
// divide amount by the divisor
void divide(int divisor) {
amount = (amount + divisor / 2) / divisor;
}
// uses integer arithmetic to calculate interest amount,
// then calls add with the interest amount
void addInterest(int rate, int divisor) {
// create DollarAmount representing the interest
DollarAmount interest {
((amount * rate + divisor / 2) / divisor) / 100, // dollars
((amount * rate + divisor / 2) / divisor) % 100 // cents
};
add(interest); // add interest to this object's amount
}
// return a string representation of a DollarAmount object
std::string toString() const {
std::string dollars{std::to_string(amount / 100)};
std::string cents{std::to_string(std::abs(amount % 100))};
return dollars + "." + (cents.size() == 1 ? "0" : "") + cents;
}
private:
int64_t amount{0}; // dollar amount in pennies
};
我尝试了几件事,但我将代码恢复为原始形式,因为其他代码不起作用。当前算法使用正常舍入。作者并没有很好地解释舍入系统。
编辑:这也是使用的主程序。
// Ex. 5.31: Interest.cpp
// Compound-interest calculations with class DollarAmount and integers.
#include <iostream>
#include <iomanip>
#include <string>
#include "DollarAmount.h"
using namespace std;
int main() {
DollarAmount d1{123, 45}; // $123.45
DollarAmount d2{15, 76}; // $15.76
cout << "After adding d2 (" << d2.toString() << ") into d1 ("
<< d1.toString() << "), d1 = ";
d1.add(d2); // modifies object d1
cout << d1.toString() << "\n";
cout << "After subtracting d2 (" << d2.toString() << ") into d1 ("
<< d1.toString() << "), d1 = ";
d1.subtract(d2); // modifies object d1
cout << d1.toString() << "\n";
cout << "After subtracting d1 (" << d2.toString() << ") from d2 ("
<< d2.toString() << "), d2 = ";
d2.subtract(d1); // modifies object d2
cout << d2.toString() << "\n";
cout << "After dividing d1 (" << d1.toString() << ") by 2, d1 = ";
d1.divide(2); // modifies object d1
cout << d1.toString() << "\n\n";
cout << "Enter integer interest rate and divisor. For example:\n"
<< "for 2%, enter: 2 100\n"
<< "for 2.3%, enter: 23 1000\n"
<< "for 2.37%, enter: 237 10000\n"
<< "for 2.375%, enter: 2375 100000\n";
int rate; // whole-number interest rate
int divisor; // divisor for rate
cin >> rate >> divisor;
DollarAmount balance{1000, 0}; // initial principal amount in pennies
cout << "\nInitial balance: " << balance.toString() << endl;
// display headers
cout << "\nYear" << setw(20) << "Amount on deposit" << endl;
// calculate amount on deposit for each of ten years
for (unsigned int year{1}; year <= 10; year++) {
// increase balance by rate % (i.e., rate / divisor)
balance.addInterest(rate, divisor);
// display the year and the amount
cout << setw(4) << year << setw(20) << balance.toString() << endl;
}
}
我目前正在使用输入 2 100 和 5 1000000 进行测试。
如果表达式 mod 1 为 0.5,我尝试设置条件,如果表达式为真,则使用正常美分,如果表达式 mod 2 为偶数,则使用正常美分加零,如果表达式 mod 2 为奇数,则使用加零。这最终变得一团糟,甚至没有工作,并且在我测试它时以某种方式摆脱了所有的美分。对于银行家的舍入算法,输入 2 100 应返回 1218.98 10 年,而 5 1000000 应始终返回 1000,因为它舍入到最接近的偶数,向下舍入。
编辑 2:我对代码进行了一些修改,我想我已经想到了我将使用的算法。这是修改后的源代码。
// Ex. 5.31: DollarAmount.h
// DollarAmount class gets two parameter constructor
#include <string>
#include <iostream>
#include <cmath>
class DollarAmount {
public:
// initialize amount from an int64_t value
explicit DollarAmount(int64_t dollars, int64_t cents) : amount{dollars * 100 + cents} { }
// add right's amount to this object's amount
void add(DollarAmount right) {
// can access private data of other objects of the same class
amount += right.amount;
}
// subtract right's amount from this object's amount
void subtract(DollarAmount right) {
// can access private data of other objects of the same class
amount -= right.amount;
}
// divide amount by the divisor
void divide(int divisor) {
amount = (amount + divisor / 2) / divisor;
}
// uses integer arithmetic to calculate interest amount,
// then calls add with the interest amount
void addInterest(int rate, int divisor) {
// create DollarAmount representing the interest
DollarAmount interest {
((amount * rate + divisor / 2) / divisor) / 100, // dollars
((amount * rate + divisor / 2) / divisor) % 100 // cents
};
if (static_cast<int64_t>((((amount * rate + divisor / 2) / divisor) % 1) * 10) == 5) {
if (interest.amount % 2 == 1) {
interest.amount--;
}
std::cout << "test";
}
add(interest); // add interest to this object's amount
}
// return a string representation of a DollarAmount object
std::string toString() const {
std::string dollars{std::to_string(amount / 100)};
std::string cents{std::to_string(std::abs(amount % 100))};
return dollars + "." + (cents.size() == 1 ? "0" : "") + cents;
}
private:
int64_t amount{0}; // dollar amount in pennies
};
所以本质上我的计划是正常创建利息对象,然后我检查是否满足银行家的舍入条件,然后如果 interest.amount 变量 % 2 == 1,这意味着它没有四舍五入到最接近的偶数整数. 如果满足此条件,它会减少 interest.amount 变量。这似乎有点混乱,但由于似乎没有更简单的方法可以做到这一点,我想我会尝试这种方法。问题是 if 语句目前无法检查是否需要银行家的四舍五入。
编辑 3:添加评论
// Ex. 5.31: DollarAmount.h
// DollarAmount class gets two parameter constructor
#include <string>
#include <iostream>
#include <cmath>
class DollarAmount {
public:
// initialize amount from an int64_t value
explicit DollarAmount(int64_t dollars, int64_t cents) : amount{dollars * 100 + cents} { }
// add right's amount to this object's amount
void add(DollarAmount right) {
// can access private data of other objects of the same class
amount += right.amount;
}
// subtract right's amount from this object's amount
void subtract(DollarAmount right) {
// can access private data of other objects of the same class
amount -= right.amount;
}
// divide amount by the divisor
void divide(int divisor) {
amount = (amount + divisor / 2) / divisor;
}
// uses integer arithmetic to calculate interest amount,
// then calls add with the interest amount
void addInterest(int rate, int divisor) {
// create DollarAmount representing the interest
DollarAmount interest {
((amount * rate + divisor / 2) / divisor) / 100, // dollars
((amount * rate + divisor / 2) / divisor) % 100 // cents
};
// banker's rounding special case
std::cout << (((amount * rate + divisor / 2) / divisor) % 1) * 10 << std::endl;
if (static_cast<int64_t>((((amount * rate + divisor / 2) / divisor) % 1) * 10) == 5) {
// if interest.amount is odd, implying normal rounding deviated from banker's rounding
if (interest.amount % 2 == 1) {
interest.amount--; // deincrement interest.amount to account for banker's rounding
}
std::cout << "test";
}
add(interest); // add interest to this object's amount
}
// return a string representation of a DollarAmount object
std::string toString() const {
std::string dollars{std::to_string(amount / 100)};
std::string cents{std::to_string(std::abs(amount % 100))};
return dollars + "." + (cents.size() == 1 ? "0" : "") + cents;
}
private:
int64_t amount{0}; // dollar amount in pennies
};
编辑 4:好的,所以我想我将使用正常舍入然后检查是否需要银行家舍入,然后如果是并且 interest.amount 是奇数,这意味着它偏离了银行家舍入,它会减少它。剩下的唯一问题是我的 if 语句检查是否需要银行家四舍五入是行不通的。
解决方案
它是这样的:
// Ex. 5.31: DollarAmount.h
// DollarAmount class gets two parameter constructor
#include <string>
#include <cmath>
#include <iostream>
class DollarAmount {
public:
// initialize amount from an int64_t value
explicit DollarAmount(int64_t dollars, int64_t cents) : amount{dollars * 100 + cents} { }
// add right's amount to this object's amount
void add(DollarAmount right) {
// can access private data of other objects of the same class
amount += right.amount;
}
// subtract right's amount from this object's amount
void subtract(DollarAmount right) {
// can access private data of other objects of the same class
amount -= right.amount;
}
// divide amount by the divisor
void divide(int divisor) {
amount = (amount + divisor / 2) / divisor;
}
// uses integer arithmetic to calculate interest amount,
// then calls add with the interest amount
void addInterest(int rate, int divisor) {
// create DollarAmount representing the interest
DollarAmount interest {
((amount * rate + divisor / 2) / divisor) / 100, // dollars
((amount * rate + divisor / 2) / divisor) % 100 // cents
};
add(interest); // add interest to this object's amount
}
// return a string representation of a DollarAmount object
std::string toString() const {
std::string dollars{std::to_string(amount / 100)};
std::string cents{std::to_string(std::abs(amount % 100))};
return dollars + "." + (cents.size() == 1 ? "0" : "") + cents;
}
void bankersRounding() {
std::cout << "money: " << amount << " cents" << std::endl;
int dollarsPart = amount/100;
int penniesPart = amount%100;
std::cout << " - dollars: " << dollarsPart << std::endl;
std::cout << " - pennies: " << penniesPart << std::endl;
// if it is equally distant from upper and lower integers,
// then apply banker's rounding
if (penniesPart==50)
{
// if the lower integer is zero, then round down to zero
if(dollarsPart==0)
{
std::cout << "it is zero" << std::endl;
amount -= 50;
}
// if the lower integer is even, then round down
else if ((dollarsPart%2)==0)
{
std::cout << "even" << std::endl;
amount -= 50;
}
// else the lower integer is odd, so round up
else {
std::cout << "odd" << std::endl;
amount += 50;
}
}
}
private:
int64_t amount{0}; // dollar amount in pennies
};
int main()
{
DollarAmount d1(0, 0);
DollarAmount d2(0, 50);
d1.add(d2);
d1.bankersRounding();
std::cout << "final: " << d1.toString() << std::endl;
return 0;
}
推荐阅读
- pythonanywhere - PythonAnywhere – 如何使用我安装的模块?
- reactjs - 如何将此子组件包装在高阶组件中?
- javascript - 如何使用 splice 和 slice 将一个数组放入另一个数组
- html - HTML5视频源是否有可能有#
- json - 没有使用正则表达式作为值创建有效的 json
- clojure - 使用 Datomic 返回 Map 而不是 Vector 时出错
- ios - iOS Swift UI 测试点击警报按钮
- c# - SignalR 集线器 Context.ConnectionId 对象引用错误
- c - 有人可以解释一下这段代码以及它到底做了什么吗?
- wcf - ASP .NET Core 2.0 部署无法与生产中的 WCF 服务连接