如何在c++中将64位整数乘以分数,同时最小化错误
How to multiply a 64 bit integer by a fraction in C++ while minimizing error?
给定64位(带符号)long long
或__int64
,您如何将其乘以任意分数,同时最小化错误?
三个简单的草图:
int64_t numerator = ...;
int64_t denominator = ...;
int64_t x = ...;
// a, lossy double conversion for large values
double fraction = static_cast<double>(numerator) / static_cast<double>(denominator);
int64_t result = x * fraction;
// b, divide first, problem if denominator value near (or even larger) x
int64_t result = x / denominator;
result *= numerator;
// c, multiply first, problem if multiplication overflows
int64_t result = x * numerator;
result /= denominator;
如果x * n / d
在数学上不能产生整数,我可以将结果截断到最接近的整数。
您可以使用以下命令:
const int64_t q = x / denominator;
const int64_t r = x - q * denominator;
// x = q * denominator + r;
const int64_t result = q * numerator + ((r * numerator) / denominator);
注意:用std::div
族可以同时得到商和余。
注意:Sander De Dycker指出,当r * numerator / denominator
溢出
对于x / denominator
溢出的特殊情况x = INT64_MIN, denominator = -1
或多或少是从这里复制的,这对我来说似乎是最有意义的:
int64_t muldiv64(const int64_t x, const int64_t n, const int64_t d)
{
/* find the integer and remainder portions of x/d */
const int64_t div = x / d;
const int64_t mod = x % d;
return div * n + (mod * n) / d;
}
改进提供的答案(这减少了b
较大时的溢出):
int64_t muldiv64(const int64_t a, const int64_t b, const int64_t d)
{
/* find the integer and remainder portions of x/d */
const int64_t diva = a / d;
const int64_t moda = a % d;
const int64_t divb = b / d;
const int64_t modb = b % d;
return diva * b + moda * divb + moda * modb / d;
}
没有必要编写奇怪的代码来避免使用模数运算:编译器可以做替换,你可以有一个更可读的代码。
编辑:任何更复杂的代码可能都不值得研究。如果需要更高的精度,最好是使用128位算法或使用任意精度的整数库(参见http://sourceforge.net/projects/cpp-bigint/)
相关文章:
- 找到两对数字,使它们的乘积的绝对差最小化
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 超轻 - 如何最小化窗口
- 在C++中使用 GSL 最小化
- 在C++中最小化变量的范围
- 当只有一个线程主要使用该对象而其他线程很少使用它时,如何最小化该对象的互斥锁锁定?
- "最小化"按钮不会出现在 MFC 对话框中
- 从小于或等于某个 N 的数字列表中最小化或找到 n 个理想的子集和
- 如何排列二进制字符串以最小化它们之间的距离
- 最小化 C++ 中的内存使用
- 禁用 GPO 的空气抖动最小化
- 如何隐藏最大化和最小化按钮并在qml应用程序窗口中显示关闭按钮?
- 如何使用 stl 最小化 c++ 中所有打开的窗口
- 如何最小化嵌入式平台上的内存分配
- 可见程序或最小化程序时的过程ID更改
- 删除/最小化GIT合并冲突
- 当模式窗口最小化时,最小化所有应用程序窗口(在 Linux 上)
- 应用程序最小化时单击显示桌面/最小化全部
- 使用vector最小化堆分配会导致seg错误
- 如何在c++中将64位整数乘以分数,同时最小化错误