我正在阅读最多2个小数位的“浮动”数字,例如下面的内容:
122
122.3
122.34
并且需要通过乘以(想象存储美元/美分)将它们转换为整数值
int i;
double d;
scanf( "%lf", &d );
i = d * 100;
例如18.56
将转换为1855
有没有办法将值读取为double并将其正确转换为int?
TIA
答案 0 :(得分:5)
使用舍入转换为int的最简单方法:
i = (int)floor(d * 100 + 0.5);
如果您的号码总是正数:
i = (int)(d * 100 + 0.5);
1.565和1.575之间的值将变为157. 2.135和2.145之间的值将变为214.
这样,如果你有一个像1.56999这样的数字,那就会变成157。
这不是“解决精确损失” - 无论这意味着什么。它只是四舍五入。
如果某个值恰好在两个数字之间(例如d为1.125),那么您可能会得到意外结果。在这种情况下,所有数字只有两位小数,所以这不是问题。如果数字不限于更多小数位,您需要更仔细地考虑如何处理像1.125这样的数字。
答案 1 :(得分:0)
存储在浮点中的值将被舍入。乘以10的幂只会放大误差。如果你不想要有任何舍入错误,你需要立即将值读入一个整数,如果需要乘以该值的因子,可能会跟踪小数点的位置:
std::string tmp;
if (std::cin >> tmp) {
std::string::size_type decimal_point = tmp.rfind('.');
int power(0);
if (decimal_point != tmp.npos) {
tmp.erase(tmp.begin() + decimal_point);
power = int(decimal_point) - int(tmp.size());
}
int value;
if (std::istringstream(tmp) >> value) {
std::cout << "read " << value << "e" << power << "\n";
}
}
此代码仅处理相对简单的浮点数,但肯定会使用您引用的形式。
另一种方法是使用十进制浮点,在处理十进制值时没有舍入问题。遗憾的是,它们尚未作为标准C ++库的一部分提供。但是,有些编译器会提供扩展来处理十进制浮点数。
答案 2 :(得分:0)
问题是你转换为float(通过scanf
)是一个近似值,它会失去预期的精确十进制值。而是使用:
int dollars = 0, cents = 0;
scanf("%d.%d", &dollars, ¢s);
cents += 100*dollars;
或类似。
答案 3 :(得分:0)
如果您确定数字最多只有两位数并且数量中等,则将它们读为double
,乘以100,舍入到最接近的整数将产生正确的数字结果。 (简单地将double
转换为整数截断,而不是舍入到最近,并且由于浮点舍入错误,有时会产生不正确的结果。您可以使用round
函数进行舍入。)
使用double
以这种方式处理输入不一定是最好的方法。
答案 4 :(得分:0)
OP几乎拥有它,只需要添加round()
并进行错误检查。
round()
很好地绕到最近,与0相关。
12.34等值将导致1234.
由于FP问题,在12.345边界处的值可能会返回1234或1235,但OP 3的例子并没有超过0.01。
+或 - 数字没问题。
#include <math.h>
...
int i;
double d_dollars;
double d_cents;
if (1 != scanf( "%lf", &d_dollars)) handle_error();
d_cents = round(d_dollars * 100.0);
if ((d_cents < INT_MIN) || (d_cents > INT_MAX)) handle_error();
i = (int) d_cents;