pf8*_*f85 4 c int 64-bit computer-science
在我的平台上,unsigned long long是64位(8字节).假设我有两个这样的变量:
unsigned long long partialSize;
unsigned long long totalSize;
//somehow determine partialSize and totalSize
Run Code Online (Sandbox Code Playgroud)
如何可靠地确定百分比(四舍五入到附近的整数)partialSize是totalSize多少?(如果可能的话,如果我不必假设前者小于后者,那将是很好的,但如果我真的必须做出这个假设,那就没关系.但我们当然可以假设两者都是非-负.)
例如,以下代码是完全防弹的吗?我担心它会包含某种舍入,转换或转换错误,这些错误可能导致比率在某些条件下失控.
unsigned long long ratioPercentage
= (unsigned long long)( ((double)partialSize)/((double)totalSize) * 100.0 );
Run Code Online (Sandbox Code Playgroud)
它不是完全防弹的.doublemantissae只有53位(52 + 1隐式),所以如果你的数字大于2^53,转换到double通常会引入舍入错误.但是,与数字本身相关的舍入误差非常小,因此导致整数值的百分比计算将引入比转换更多的不准确性.
一个可能更严重的问题是,这将始终向下舍入,例如,对于totalSize = 1000和partialSize = 99,它将返回9而不是更接近的值10.你可以通过0.5在转换之前添加更好的舍入unsigned long long.
只使用整数运算可以得到精确的结果(如果最终结果没有溢出),如果partialSize不是太大则相当容易:
if (partialSize <= ULLONG_MAX / 100) {
unsigned long long a = partialSize * 100ULL;
unsigned long long q = a / totalSize, r = a % totalSize;
if (r == 0) return q;
unsigned long long b = totalSize / r;
switch(b) {
case 1: return q+1;
case 2: return totalSize % r ? q : q+1; // round half up
default: return q;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想要地板,天花板或圆形半对偶,可以轻松修改.
如果totalSize >= 100和ULLONG_MAX / 100 >= partialSize % totalSize,没关系,
unsigned long long q0 = partialSize / totalSize;
unsigned long long r = partialSize % totalSize;
return 100*q0 + theAbove(r);
Run Code Online (Sandbox Code Playgroud)
在其他情况下,它变得更加繁琐,我并不热衷于这样做,但如果你需要,我可以被说服.
| 归档时间: |
|
| 查看次数: |
1792 次 |
| 最近记录: |