咱们经过简单的代码试验一下:code
int newWidth, newHeight; GetThumbnailSize(200, 200, 100, 100, out newWidth, out newHeight); Console.WriteLine("{0}, {1}", newWidth, newHeight); GetThumbnailSize(300, 300, 100, 100, out newWidth, out newHeight); Console.WriteLine("{0}, {1}", newWidth, newHeight);
获得的结果是:orm
100, 100 99, 100
第一个结果天然没有问题,可是在第二个结果中为何是99而不是100?为此,咱们再经过如下的代码来观察一番:ci
ratio: 0.3333333333333333333333333333 new value: 99.99999999999999999999999999 to int: 99
可见,虽然使用了decimal,精度已经很是高的,可是在通过了一除一乘,它仍是没有恢复到最精确值。虽然一直说要注意浮点数计算时的精度问题,可是对于这个问题许多朋友每每只是理解到“不能直接两个浮点数相等”,包括我本身的第一印象。但事实上,从上面的结果也能够看出,把一个浮点数直接转换成整形,它即是使用了“去尾”而不是“四舍五入”的方法。所以,虽然newValue的值无比接近100,可是在强制去尾后它仍是变成了99。编译器
若是要在原来的方法中改变这个问题,最简单的方法多是把最后的强制转型替换成Math.Round方法。Math.Round方法使用四舍五入,应该可以解决问题。不过若是只是这样的话收获不大,咱们再仔细想一想,应该如何作到尽量的精确。it
两个浮点数相除可能会丧失精度,但若是是乘法操做,在通常状况下精度是不会丢失的,除非发生了溢出的话,或者小数位数太多。所以在计算过程当中为了保持精度,咱们应该尽量的作乘法,而不是做除法。例如如下的判断:io
if ((decimal)desiredWidth / originalWidth < (decimal)desiredHeight / originalHeight)
其实最好改写成“等价”的乘法操做。编译