C#检查进度的奇怪问题

时间:2013-08-21 21:41:46

标签: c#

我在构造函数中有一个循环,它创建并初始化一个锯齿状的对象数组。在循环内部,我会在每次迭代时将其打印到控制台,以便我知道它在整个过程中有多远。它只以5的倍数打印到控制台(虽然由于某种原因它只打印在10的倍数上),所以它不会垃圾屏幕。例如,15%20%25%。

当我在Windows上运行.Net 2.0上的代码时,它每10%打印一次(而不是5%)。如果我在ARM机器上的Mono上运行相同的代码,它根本不打印任何进度。

  1. 是什么导致Mono不提供任何输出?
  2. 为什么只以10%而不是5%的增量打印?
  3. 由于

    以下是代码:

    public Map(int NumberOfRows, int NumberOfColumns)
    {
        Rows = NumberOfRows;
        Columns = NumberOfColumns;
    
        TileGrid = new Tile[NumberOfRows][];
        for (int x = 0; x < TileGrid.Length; x++)
        {
            TileGrid[x] = new Tile[NumberOfColumns];
            for (int y = 0; y < TileGrid[x].Length; y++)
            {
                TileGrid[x][y] = new Tile();
            }
    
            if (((double)x / Rows) * 100 % 5 == 0)
            {
                Console.WriteLine("{0}%", ((double)x / Rows) * 100);
            }
        }
    }
    

2 个答案:

答案 0 :(得分:5)

问题基本上是你正在对浮点数进行相等检查,这绝不是一个好主意。

这是更好 ......但仍然不好:

int percentage = (x * 100) / Rows;
if (percentage % 5 == 0)
{
    Console.WriteLine("{0}%", percentage);
}

除非你以5%的倍数结束完全,否则仍然无法打印百分比。因此,如果有12个项目,它将不起作用。试试这个:

// Before the loop
int lastPrintedPercentage = -5; // So that we always print on the first loop

// Within the loop
int percentage = (x * 100) / Rows;
if (percentage >= lastPrintedPercentage + 5)
{
    Console.WriteLine("{0}%", percentage);
    lastPrintedPercentage = percentage;
}

答案 1 :(得分:1)

由于浮点舍入误差,必须将浮点运算与机器epsilon进行比较

http://en.wikipedia.org/wiki/Machine_epsilon

根据浮点舍入误差

,此表达式永远不会为空

if(((double)x / Rows)* 100%5 == 0) 一定是 if(Math.Abs​​(((double)x / Rows)* 100%5)&lt; MACHINE_EPSILON)

但.NET Framework中没有关于机器epsilon的定义。因此,根本不使用浮点运算或使用像

这样的delta技术
var step = (double)x / Rows) * 5;
var current = step ; 

...
if((double)x / Rows) >= current)
{
    current += step;
    // Your code here
}
...