我必须将一个unsigned long int除以size_t(从一个带有size()的数组维返回),如下所示:
vector<string> mapped_samples;
vector<double> mean;
vector<unsigned long> feature_sum;
/* elaboration here */
mean.at(index) = feature_sum.at(index) /mapped_samples.size();
但是以这种方式发生整数除法(我丢失了小数部分。这没有用)
因此,我可以这样做:
mean.at(index) = feature_sum.at(index) / double(mapped_samples.size());
但是这样feature_sum.at(index)
会自动转换(临时副本)到double
,我可能会失去精确度。我该如何解决这个问题?我必须使用一些库吗?
将无符号long转换为double时可能会导致精度损失(因为无符号long值可能大于double的最大值)unsigned long值是要素的总和(正值)。特征的样本可以是1000000或更多,并且特征的值的总和可以是nourmus。因此,特征的最大值为2000:2000 * 1000000或更多
(我正在使用C ++ 11)
答案 0 :(得分:4)
您可以尝试使用std::div
沿线
auto dv = std::div(feature_sum.at(index), mapped_samples.size());
double mean = dv.quot + dv.rem / double(mapped_samples.size());
答案 1 :(得分:3)
您可以使用:
// Grab the integral part of the division
auto v1 = feature_sum.at(index)/mapped_samples.size();
// Grab the remainder of the division
auto v2 = feature_sum.at(index)%mapped_samples.size();
// Dividing 1.0*v2 is unlikely to lose precision
mean.at(index) = v1 + static_cast<double>(v2)/mapped_samples.size();
答案 2 :(得分:2)
你不能做得更好(如果你想把结果存储为double
),而不是简单的
std::uint64_t x=some_value, y=some_other_value;
auto mean = double(x)/double(y);
因为使用float128
auto improved = double(float128(x)/float128(x))
通常是相同的(对于典型的输入 - 可能有罕见的输入,可以改进)。两者都有由double
(53位)的尾数长度决定的相对误差。所以简单的答案是:要么使用比double
更准确的类型,要么忘掉这个问题。
要查看相对准确度,我们假设
x=a*(1+e); // a=double(x)
y=b*(1+f); // b=double(y)
其中e
,f
的顺序为2 ^ -53。
然后'正确'的商是第一顺序e
和f
(x/y) = (a/b) * (1 + e - f)
将此转换为double
会产生另一个2 ^ -53的相对误差,即与(a/b)
的误差相同的顺序,这是天真的结果
mean = double(x)/double(y).
当然,e
和f
可以合谋取消,当其他答案中建议的方法可以获得更高的准确度时,但通常无法提高准确度。