舍入具有不同分辨率的数字

时间:2014-07-24 08:04:56

标签: c# rounding

使用C#,我需要一种优雅的方法,使用以下规则将分辨率为1/8的分数舍入到1/2的分辨率:

Round(0) = 0
Round(0.125) = 0
Round(0.25) = 0
Round(0.375) = 0.5
Round(0.5) = 0.5
Round(0.625) = 0.5
Round(0.75) = 0.5
Round(0.875) = 1
Round(1) = 1

当然,我不仅限于0到1之间的数字。 没有太多的ifs,有没有一个好方法呢?

3 个答案:

答案 0 :(得分:1)

以下代码段演示了您想要的内容。它使用一种乘以2的技术(这样我们将其变为整数)并取出一小部分。我们减去0.001M,因为我们希望0.25舍入到0和0.75舍入到0.5。通常在乘以2后舍入时,它们将被四舍五入。少量关闭确保我们将0.499和1.499四舍五入得到0和1,然后在除以2时给出正确的结果。提供的两种中点舍入技术,从零开始,甚至不会在这里做我们想要的。

public decimal MyRound(decimal input)
{
    return Math.Round(input*2-0.001M, MidpointRounding.AwayFromZero)/2;
}

void Main()
{
    var testvalues = new decimal[]{0M,0.125M,0.25M,0.375M,0.5M,0.625M,0.75M,0.875M,1M};
    foreach (var value in testvalues)
    {
        Console.WriteLine(String.Format("{0} rounds to {1}",value, MyRound(value)));
    }
}


Output: 
0 rounds to 0
0.125 rounds to 0
0.25 rounds to 0
0.375 rounds to 0.5
0.5 rounds to 0.5
0.625 rounds to 0.5
0.75 rounds to 0.5
0.875 rounds to 1
1 rounds to 1

我应该注意到我使用十进制只是因为我在脑中得到了这就是你所使用的(我认为因为我的大脑有"十进制位置"在其中。该技术将起作用好的双打...

答案 1 :(得分:1)

public double Round(double input)
{
    var rounded = Math.Round(input*2-0.0001)/2;
    return rounded;
}

答案 2 :(得分:0)

如果溢出不是问题,那么你可以先乘以8舍入到最接近的1/8;四舍五入到最接近的整数;并且除以8得到原始比例。这适用于任何合理的分数。

如果溢出是一个问题,你可以利用8是2的幂的事实,并操纵位。让左(最低有效)的位数为0到右(最高有效)为n-1,其中n将为16或32或64,具体取决于整数大小。使用该术语,首先存储位2(4位)。然后将你的数字右移3,如果设置了4位,则加1。此技术可用于任何精确分数幂为2的分数。

更新:如下所述,我最初误解了这个问题。然而,上述技术仍然有效,尽管细节略有不同。

步骤:

  1. 乘以8并转换为整数类型。
  2. 首先向右移位然后向左移位2位,然后用4位移位。
  3. 转换回原始浮点类型。
  4. 或者,深入研究浮点类型的二进制表示,并直接操作尾数位。