为什么这个浮点计算给出不同机器上的不同的结果? [英] Why does this floating-point calculation give different results on different machines?

查看:199
本文介绍了为什么这个浮点计算给出不同机器上的不同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的常规,其计算从一个浮点值的纵横比。因此对于值1.77777779,程序返回字符串16:9。我有我的机器上测试了这一点,它工作正常。

I have a simple routine which calculates the aspect ratio from a floating point value. So for the value 1.77777779, the routine returns the string "16:9". I have tested this on my machine and it works fine.

该例程被给定为:

    public string AspectRatioAsString(float f)
    {
        bool carryon = true;
        int index = 0;
        double roundedUpValue = 0;
        while (carryon)
        {
            index++;
            float upper = index * f;

            roundedUpValue = Math.Ceiling(upper);

            if (roundedUpValue - upper <= (double)0.1 || index > 20)
            {
                carryon = false;
            }
        }

        return roundedUpValue + ":" + index;
    }

现在另一台机器上,我得到完全不同的结果。所以,我的机器上,1.77777779给。16:9,而另一台机器上我得到38:21

Now on another machine, I get completely different results. So on my machine, 1.77777779 gives "16:9" but on another machine I get "38:21".

推荐答案

这里的C#specifiction的一个有趣的一点,从第4.1.6节:

Here's an interesting bit of the C# specifiction, from section 4.1.6:

浮点运算可能
  具有较高的precision进行比
  结果类型的操作。对于
  例如,某些硬件结构
  支持扩展或长双
  浮点类型具有更大的范围
  和precision比double类型,
  并隐式执行所有
  使用这种浮点运算
  更高的precision类型。只有在
  在性能上能有这样成本过高
  硬件架构中,以制成
  执行浮点运算与
  少precision,而非
  需要实施没收
  性能和precision,C#
  允许有较高的precision类型为
  用于所有浮点
  操作。除了提供更多
  precise的结果,这种情况很少有什么
  可测量的效果。

Floating-point operations may be performed with higher precision than the result type of the operation. For example, some hardware architectures support an "extended" or "long double" floating-point type with greater range and precision than the double type, and implicitly perform all floating-point operations using this higher precision type. Only at excessive cost in performance can such hardware architectures be made to perform floating-point operations with less precision, and rather than require an implementation to forfeit both performance and precision, C# allows a higher precision type to be used for all floating-point operations. Other than delivering more precise results, this rarely has any measurable effects.

这是可能的,这是对可衡量效果多亏了呼叫天花板之一。数量级的九级以浮点数字的上限,正如其他人所指出的,放大的0.000000002一个区别,因为事实证明15.99999999为16个和16.00000001为17.操作前大量不同事后略有不同的两个数字;微小的差异可能的事实,不同的机器可以在其浮点运算或多或少都有额外precision来解释。

It is possible that this is one of the "measurable effects" thanks to that call to Ceiling. Taking the ceiling of a floating point number, as others have noted, magnifies a difference of 0.000000002 by nine orders of magnitude because it turns 15.99999999 into 16 and 16.00000001 into 17. Two numbers that differ slightly before the operation differ massively afterwards; the tiny difference might be accounted for by the fact that different machines can have more or less "extra precision" in their floating point operations.

相关问题:


  • <一个href=\"http://stackoverflow.com/questions/2345534/c-xna-visual-studio-difference-between-release-and-debug-modes/2345645#2345645\">http://stackoverflow.com/questions/2345534/c-xna-visual-studio-difference-between-release-and-debug-modes/2345645#2345645

<一个href=\"http://stackoverflow.com/questions/2225503\">http://stackoverflow.com/questions/2225503

要解决您如何计算从一个浮动的纵横比具体的问题:我想可能是解决这个问题的方式完全不同。我会做一个表是这样的:

To address your specific problem of how to compute an aspect ratio from a float: I'd possibly solve this a completely different way. I'd make a table like this:

struct Ratio
{
    public int X { get; private set; }
    public int Y { get; private set; }
    public Ratio (int x, int y) : this()
    {
        this.X = x;
        this.Y = y;
    }
    public double AsDouble() { return (double)X / (double)Y; }
}

Ratio[] commonRatios = { 
   new Ratio(16, 9),
   new Ratio(4, 3), 
   // ... and so on, maybe the few hundred most common ratios here. 
   // since you are pinning results to be less than 20, there cannot possibly
   // be more than a few hundred.
};

现在你的代码是

public string AspectRatioAsString(double ratio)      
{ 
    var results = from commonRatio in commonRatios
                  select new {
                      Ratio = commonRatio, 
                      Diff = Math.Abs(ratio - commonRatio.AsDouble())};

    var smallestResult = results.Min(x=>x.Diff);

    return String.Format("{0}:{1}", smallestResult.Ratio.X, smallestResult.Ratio.Y);
}

注意code现在如何读取非常像您要执行的操作:从普通比率的这个列表中,选择一个中给定的比例和普通比例之间的差异最小化。

Notice how the code now reads very much like the operation you are trying to perform: from this list of common ratios, choose the one where the difference between the given ratio and the common ratio is minimized.

这篇关于为什么这个浮点计算给出不同机器上的不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆