Вычисление количества бит в маске подсети в C # - PullRequest
3 голосов
/ 03 января 2012

У меня есть задача для завершения в C #.У меня есть маска подсети: 255.255.128.0.

Мне нужно найти количество бит в маске подсети, которое в данном случае будет 17.

Однако мне нужнобыть в состоянии сделать это в C # БЕЗ использования библиотеки System.Net (система, в которой я программирую, не имеет доступа к этой библиотеке).

Кажется, что процесс долженбыть примерно таким:

1) Разделить маску подсети на октеты.

2) Преобразовать октеты в двоичные.

3) Подсчитать число единиц в каждом октете..

4) Вывести общее количество найденных.

Однако мой C # довольно плохой.У кого-нибудь есть знания C #, чтобы помочь?

Ответы [ 5 ]

3 голосов
/ 03 января 2012

Алгоритм подсчета битов взят из:
http://www.necessaryandsufficient.net/2009/04/optimising-bit-counting-using-iterative-data-driven-development/

string mask = "255.255.128.0";
int totalBits = 0;
foreach (string octet in mask.Split('.'))
{
    byte octetByte = byte.Parse(octet);
    while (octetByte != 0)
    {
        totalBits += octetByte & 1;     // logical AND on the LSB
        octetByte >>= 1;            // do a bitwise shift to the right to create a new LSB
    }                
}
Console.WriteLine(totalBits);

Использован самый простой алгоритм из статьи. Если производительность критична, вы можете прочитать статью и использовать более оптимизированное решение.

1 голос
/ 03 января 2012
string ip = "255.255.128.0";
string a = "";
ip.Split('.').ToList().ForEach(x => a += Convert.ToInt32(x, 2).ToString());
int ones_found = a.Replace("0", "").Length;
0 голосов
/ 03 января 2012

Решение состоит в том, чтобы использовать binary operation как

  foreach(string octet in ipAddress.Split('.'))
  {       
      int oct = int.Parse(octet);     
      while(oct !=0) 
      {
              total += oct & 1; // {1}
              oct >>=1;  //{2}          
      }   
  }

Хитрость в том, что в строке {1} binary AND имеет значение умножение , поэтому умножаем 1x0=0, 1x1=1. Так что, если у нас есть гипотетическое число

0000101001 и умножим его на 1 (поэтому в двоичном мире мы выполняем &), что не больше, чем 0000000001, мы получаем

0000101001
0000000001

Большинство вправо цифра равна 1 в обоих числах, поэтому binary AND возвращает 1, в противном случае, если ЛЮБОЙ из младшей цифры номера будет 0, результат будет 0.

Итак, здесь, в строке total += oct & 1 мы добавляем к tolal либо 1, либо 0, основываясь на этом цифровом номере.

В строке {2} вместо этого мы просто сдвигаем младший бит вправо, фактически, делив число на 2, пока оно не станет 0.

Easy.

РЕДАКТИРОВАТЬ

Это действительно для intgere и byte типов, но не используйте эту технику на floating point числах. Кстати, это очень ценное решение для этого вопроса.

0 голосов
/ 03 января 2012

Полный образец:

public int CountBit(string mask)
        {

            int ones=0;
            Array.ForEach(mask.Split('.'),(s)=>Array.ForEach(Convert.ToString(int.Parse(s),2).Where(c=>c=='1').ToArray(),(k)=>ones++));
          return ones

        }
0 голосов
/ 03 января 2012

Вы можете преобразовать число в двоичное, как это:

        string ip = "255.255.128.0";
        string[] tokens = ip.Split('.');
        string result = "";
        foreach (string token in tokens)
        {
            int tokenNum = int.Parse(token);
            string octet = Convert.ToString(tokenNum, 2);
            while (octet.Length < 8)
                octet = octet + '0';
            result += octet;
        }
        int mask = result.LastIndexOf('1') + 1;
...