0

I'm trying to convert one IP from string to Decimal using split and aggregate. Specifically I made this question about Split and Aggregate not other solutions like IpAddress or similar.

For the "192.168.0.1" ip, the number must be 3232235521

var decimalIP = "192.168.0.1".Split(".").Aggregate(0, (numIP, segment) => {
    numIP = numIP<< 8;
    return numIP + Decimal.Parse(segment);
});

This method does not work:

Decimal number = "192.168.0.1".Aggregate(0m, (numIP, segment) => {
    numIP = (long)numIP << 8;
    return (Decimal)(numIP + Decimal.Parse(segment));
});

I was also trying

var segments = "192.168.0.1".Select(segment => Decimal.Parse(segment));
var reverse = segments.Reverse();

Decimal reverseSumm = reverse.Aggregate(0m, (numIP, segment) => {
    numIP = (long)numIP << 8;
    return (Decimal)(numIP + segment);
});

Decimal directSumm = segments.Aggregate(0m, (numIP, segment) => {
    numIP = (long)numIP << 8;
    return (Decimal)(numIP + segment);
});

The number

How to do it?

joseluisbz
  • 1,491
  • 1
  • 36
  • 58
  • 3
    Are you trying to learn the Aggregate function? If not, is there any reason you can't use `System.Net.IPAddress.Parse` for this task? Then you can use `System.BitConverter.ToUInt32(ip.GetAddressBytes(), 0)` to "aggregate" the bytes. In any case you should make sure whether you want them bytes to be "aggregated" from left to right or the other way around (Little- / Big-Endian). Edit: Judging by your edit, you might actually need to use `.Reverse().ToArray()` to reverse the byte order. Still the result would be 3232235521 and not 3194548201 – MrPaulch Aug 09 '21 at 16:25
  • @TimSchmelter I get negative number, and the integer would be overflow – joseluisbz Aug 09 '21 at 16:30
  • 2
    Does this answer your question? [Convert IP Address to UInt32/UInt64 in .NET Core](https://stackoverflow.com/questions/40410517/convert-ip-address-to-uint32-uint64-in-net-core) and [How do you parse an IP address string to a uint value in C#?](https://stackoverflow.com/questions/36831/how-do-you-parse-an-ip-address-string-to-a-uint-value-in-c) and [How to convert an IPv4 address into a integer in C#?](https://stackoverflow.com/questions/461742/how-to-convert-an-ipv4-address-into-a-integer-in-c) –  Aug 09 '21 at 16:31
  • @MrPaulch I was times by 255 instead of 256... I'm mistake! – joseluisbz Aug 09 '21 at 16:33
  • IPv4 addresses are natively `UInt32` values. Why would you want `decimal` when `uint` is **right there**? Also [`System.Net.IPAddress.Parse()`](https://learn.microsoft.com/en-us/dotnet/api/system.net.ipaddress.parse) – Joel Coehoorn Aug 09 '21 at 16:58

1 Answers1

0

There are multiple issues here.

  • Your question is constantly changing
  • Bit shift operations are not allowed for decimals as they are floating point numbers
  • Your aggregate function needs to have the same return value type as its input value type
  • You can't add a string to a numeric type without parsing it to a numeric type first.
  • You can't use an int type as it uses 32 bit to represent a range including negative numbers, but uint is suited to represent a 32 bit positive number - which an IP address basically is.

This would work:

Decimal directSum = "192.168.0.1".Split(".").Aggregate(0m, (numIP, segment) => {
    numIP = (uint)numIP << 8;
    return numIP + Decimal.Parse(segment);
});

But what this is basically doing is casting inside a loop, which is not the most elegant way to do things. I'ld recommend operating with uint and doing the cast once you are finished:

            Decimal directSum = "192.168.0.1".Split(".").Aggregate(0u, (numIP, segment) => {
                numIP = numIP << 8;
                return numIP + uint.Parse(segment);
            });

Or if you want to keep using var:

            var directSum = (decimal) "192.168.0.1".Split(".").Aggregate(0u, (numIP, segment) => {
                numIP = numIP << 8;
                return numIP + uint.Parse(segment);
            });

I`d also propose to use uint and not decimal for your result, if it's not a hard requirement to use decimal:

            var directSum = "192.168.0.1".Split(".").Aggregate(0u, (numIP, segment) => {
                numIP = numIP << 8;
                return numIP + uint.Parse(segment);
            });
Christoph Sonntag
  • 4,459
  • 1
  • 24
  • 49