将size_t除以unsigned long并将结果赋值为double

时间:2017-05-24 16:23:45

标签: c++ c++11 precision arbitrary-precision

我必须将一个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)

3 个答案:

答案 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)

其中ef的顺序为2 ^ -53。

然后'正确'的商是第一顺序ef

(x/y) = (a/b) * (1 + e - f)

将此转换为double会产生另一个2 ^ -53的相对误差,即与(a/b)的误差相同的顺序,这是天真的结果

mean = double(x)/double(y).

当然,ef可以合谋取消,当其他答案中建议的方法可以获得更高的准确度时,但通常无法提高准确度。