3

I have a task to complete in C#. I have a Subnet Mask: 255.255.128.0.

I need to find the number of bits in the Subnet Mask, which would be, in this case, 17.

However, I need to be able to do this in C# WITHOUT the use of the System.Net library (the system I am programming in does not have access to this library).

It seems like the process should be something like:

1) Split the Subnet Mask into Octets.

2) Convert the Octets to be binary.

3) Count the number of Ones in each Octet.

4) Output the total number of found Ones.

However, my C# is pretty poor. Does anyone have the C# knowledge to help?

QuietLeni
  • 139
  • 1
  • 3
  • 12
  • 1
    How exactly are you running C# without any of the BCL libraries? Or do you mean specifically the `System.Net` _namespace_? – Oded Jan 03 '12 at 11:29
  • 1
    So you didn't try anything for any of your 4 steps yet? – sth Jan 03 '12 at 11:30
  • [Elegantly determine if more than one boolean is “true”](http://stackoverflow.com/questions/377990/elegantly-determine-if-more-than-one-boolean-is-true) – Devendra D. Chavan Jan 03 '12 at 11:35
  • I had already tried it and made a hash of it and I had got stuck when trying to do something like "byte octetByte = byte.Parse(octet);" – QuietLeni Jan 03 '12 at 11:53

5 Answers5

3

Bit counting algorithm taken from:
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);

The most simple algorithm from the article was used. If performance is critical, you might want to read the article and use a more optimized solution from it.

Rotem
  • 21,452
  • 6
  • 62
  • 109
  • Note that this solution will give the same result for "255.255.0.128" as for "255.255.128.0". Yet the former isn't a valid IPv4 subnet mask. So you can't use it to validate a mask. – Peter M Oct 20 '17 at 12:30
1
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;
Tomislav Markovski
  • 12,331
  • 7
  • 50
  • 72
0

You can convert a number to binary like this:

        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;
juergen d
  • 201,996
  • 37
  • 293
  • 362
  • So, to answer the question, use the above on each part of the subnet mask. If the subnet mask is a string, split on the `.` and parse the number. Then, count the instances of a 1 in the string, maybe as `var onesInResult = result.replace("0", "").Length;` – George Duckett Jan 03 '12 at 11:31
0

A complete sample:

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

        }
Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
0

The solution is to use a binary operation like

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

The trick is that on line {1} the binary AND is in sence a multiplication so multiplicating 1x0=0, 1x1=1. So if we have some hypothetic number

0000101001 and multiply it by 1 (so in binary world we execute &), which is nothig else then 0000000001, we get

0000101001
0000000001

Most right digit is 1 in both numbers so making binary AND return 1, otherwise if ANY of the numbers minor digit will be 0, the result will be 0.

So here, on line total += oct & 1 we add to tolal either 1 or 0, based on that digi number.

On line {2}, instead we just shift the minor bit to right by, actually, deviding the number by 2, untill it becomes 0.

Easy.

EDIT

This is valid for intgere and for byte types, but do not use this technique on floating point numbers. By the way, it's pretty valuable solution for this question.

Tigran
  • 61,654
  • 8
  • 86
  • 123