英文:
How to get accurate result of two double value division if one is divisible by another?
问题
如果已知一个双精度值可以被另一个整除(即,在数学中a/b得到一个整数),如何在C++中获取准确的整数结果?[示例代码]
int main(int argc, char* argv[]) {
double price = 1235.1;
double step = 0.1;
// 输出 12350,期望输出 12351
std::cout << int(price/step) << std::endl;
price = 1235.2;
step = 0.1;
// 输出 12352,正确
std::cout << int(price/step) << std::endl;
};
英文:
If one double value is already known divisible by another(that is, a/b gives an integer in mathmatics), how can I get the accurate integer result in C++? example code
int main(int argc, char* argv[]) {
double price = 1235.1;
double step = 0.1;
// prints 12350, 12351 expected
std::cout << int(price/step) << std::endl;
price = 1235.2;
step = 0.1;
// prints 12352, ok
std::cout << int(price/step) << std::endl;
};
答案1
得分: 4
以下是您要翻译的内容:
To answer your exact question:
> If one double value is already known divisible by another (that is, a/b gives an integer in mathematics), how can I get the accurate integer result in C++?
You just divide them by each other exactly as you would naively expect.
#include <iostream>
#include <iomanip> //std::setprecision
int main()
{
std::cout << std::setprecision(20);
//2^7, aka 128, exactly representable in double precision
constexpr double price = 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0;
std::cout << price << " = 2.0^7 exact\n";
//(1/2)^4, aka 1/16, aka 0.0625, exactly representable in double precision
constexpr double step = 0.5 * 0.5 * 0.5 * 0.5;
std::cout << step << " = 0.5^4 exact\n";
//(2^7)/((1/2)^4), exactly representable in double precision
constexpr double d_result = price / step;
std::cout << d_result << " = (2^7)/((1/2)^4) exact\n";
// as an integer
constexpr int i_result = d_result;
std::cout << i_result << " = 2048 exact\n";
//there is no difference between d_result and i_result
constexpr double difference = d_result - i_result;
static_assert(difference == 0.0);
}
This compiles, so the static assert establishes there is no difference between the integer representation and the double representation.
It prints:
128 = 2.0^7 exact
0.0625 = 0.5^4 exact
2048 = (2^7)/((1/2)^4) exact
2048 = 2048 exact
The reason this doesn't work for you:
Your doubles are known to not be evenly divisible by each other because the value of step
is not 0.1, it is 0.100000001490116119, which is the 64-bit floating-point number closest to the real number 1/10.
If you want exactness like this, use a data type with exact representation, e.g., instead of storing dollars as a double, store cents as an integer. (Or use a library that provides arbitrary precision rational numbers. GMP is a popular choice when LGPL is an acceptable license)
英文:
To answer your exact question:
> If one double value is already known divisible by another(that is, a/b gives an integer in mathmatics), how can I get the accurate integer result in C++?
You just divide them by each other exactly as you would naively expect.
#include <iostream>
#include <iomanip> //std::setprecision
int main()
{
std::cout << std::setprecision(20);
//2^7, aka 128, exactly representable in double precision
constexpr double price = 2.0*2.0*2.0*2.0*2.0*2.0*2.0;
std::cout << price << " = 2.0^7 exact\n";
//(1/2)^4, aka 1/16, aka 0.0625, exactly representable in double precision
constexpr double step = 0.5*0.5*0.5*0.5;
std::cout << step << " = 0.5^4 exact\n";
//(2^7)/((1/2)^4), exactly representable in double precision
constexpr double d_result = price/step;
std::cout << d_result << " = (2^7)/((1/2)^4) exact\n";
// as an integer
constexpr int i_result = d_result;
std::cout << i_result << " = 2048 exact\n";
//there is no difference between d_result and i_result
constexpr double difference = d_result - i_result;
static_assert(difference == 0.0);
}
This compiles, so the static assert establishes there is no difference between the integer representation and the double representation.
It prints:
128 = 2.0^7 exact
0.0625 = 0.5^4 exact
2048 = (2^7)/((1/2)^4) exact
2048 = 2048 exact
The reason this doesn't work for you:
Your doubles are known to not be evenly divisible by each other, because the value of step
is not 0.1, it is 0.100000001490116119, which is the 64bit floating point number closest to real number 1/10.
If you want exactness like this, use a data type with exact representation, e.g. instead of storing dollars as a double, store cents as an integer. (Or use a library that provides arbitrary precision rational numbers. GMP is a popular choice when LGPL is an acceptable license)
答案2
得分: 2
你不需要。浮点数不是精确的。如果你想要精确的算术运算,请不要使用浮点数。如评论中所提到的,你可以使用int cents
而不是float dollars
。
然而,将其转换为int
会截断小数部分,因此,只要提供的(int)price % (int) step == 0
,且两者都为正数,你可以通过以下方式获得所需的输出:
std::cout << int((price+step*0.5)/step) << std::endl;
英文:
You don't. Floating point numbers are not exact. If you want exact arithmetics do not use floating point numbers. As mentioned in a comment, rather than float dollars
you can work with int cents
.
However, conversion to int
truncates the fractional part, hence, provided (int)price % (int) step == 0
and both are positive you can get the desired output via:
std::cout << int((price+step*0.5)/step) << std::endl;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论