舍入到给定数组中最接近的数字

时间:2016-07-20 00:06:09

标签: c# rounding

在发布之前,我查看了这两个答案:

C# Finding Nearest Number in Array

Round integer to nearest high number in array

虽然第一个对于其中一个答案中提到的扩展方法有些帮助,但我无法理解它的深度,这将允许我修改和实现它以适应我的特定情况,第二个因为它的数组长度很短,所以不适合我的需要。如果我使用数组存储所有基数为2的数字达到2.68亿,那么它将有相对大量的条目。

基本上我在这里要做的是采用RoundedSpeed(使用Math.Round将其四舍五入为整数)并将其四舍五入到最接近的数字(它必须永远不会向下舍入,只有向上),这是电源应用于2的结果(示例编号包括16384,32768,65536,131072等)

对于这个特定的例子,我想要舍入的数字是32768.(虽然其他方法可能需要另一个数字,但这对我来说是一个问题,并且超出了本例的范围)。

这是我现在的代码:

double Speed = Math.Pow(2, ((-900 + Time) / -60)) - 1;
double RoundedSpeed = Math.Round(Speed);

最初我正在考虑使用数组来存储相关的数字以进行舍入,但是有没有其他方法可以将RoundedSpeed舍入到最接近的基数2整数?

4 个答案:

答案 0 :(得分:4)

试试这个:

var x = 56;
var y = (int)Math.Pow(2.0, Math.Ceiling(Math.Log(x, 2.0)));

在这种情况下,结果为64。

实际上,这是确定n 2 ^ n = x的内容,但由于n可能是一个小数量,因此使用Ceiling将此数字提升到最接近的整数(或如果已经是整数,请保留它。所以n2 = Ceiling(n)。然后,它会简单地计算2 ^ n2以获得y的结果。

答案 1 :(得分:3)

我会使用循环:

double RoundedSpeed = Math.Round(Speed);
int maxAllowed = 100; // prevent infinite loop
for (int i=1; i < maxAllowed; i++)
{
    double number = Math.Pow(2.0, (double)i);
    if (number > RoundedSpeed)
        return number;
}

如果你不是一个返回某个东西的方法,那么代替返回数字,用数字做一些有用的东西然后添加&#34; break;&#34;停止循环。

您希望添加错误处理以确保不会溢出最大整数值,并且如果您在达到maxAllowed时找不到数字,请执行一些有用的操作。可能有更好的解决方案,但这是一个简单的解决方案。溶液...

答案 2 :(得分:3)

使用按位运算可以非常有效地执行此操作。我在这里使用ulong作为输入和输出。这将很快运行。

ulong FancyRound(ulong value) {
    value -= 1;
    value |= value >> 1;
    value |= value >> 2;
    value |= value >> 4;
    value |= value >> 8;
    value |= value >> 16;
    value |= value >> 32;
    return value + 1;
}

你可以像这样使用它:

for (ulong i = 1; i < 10; i++) {
    Console.WriteLine("{0}: {1}", i, FancyRound(i));
}

输出:

1: 1
2: 2
3: 4
4: 4
5: 8
6: 8
7: 8
8: 8
9: 16

它的工作原理是将所有设置位“级联”,以便在完成所有|之后,将设置所有低位,直到最高有效位。之后,结果递增以获得2的舍入幂。

答案 3 :(得分:1)

我会这样做,我没有基准测试,所以我不会对速度提出任何要求:

    long input = 32111;
    long powerTwo = 1;
    int count = 0;
    int maxCount = 63; //You can't return 2^64 in a long so 63 should be the max here, as we start at 2^0!
    while (input > powerTwo && count < maxCount) {
        count++;
        powerTwo <<= 1;
    }
    return powerTwo;

输出32,768,因为长(或至少下半部分)在内存中表示为000000001(即1)而<<=操作只是将位左移1并将结果赋给{ {1}}因此,对于下一次迭代,它变为000000010(这是2),然后它只是在它大于powerTwo时将它得到的值剔除。

如果您知道它会在溢出之前终止,那么您可以删除计数内容。