# Confused Newbie question: Decimal to IP

Discussion in 'Perl Misc' started by Monica Roman, May 10, 2004.

1. ### Monica RomanGuest

I've read a lot of the threads on this conversion but could not figure
out which one is the correct function.

I have never written PERL before, but I want to give it a try and be
able to convert decimal numbers into IP addresses in the PERL script
used to load the IPs plus other data into an Oracle database. Right
now I use a SQL function within Oracle, but it slows down everything!

Can someone help the translate into PERL the following SQL function?

create or replace function int2ip(ip int)
return varchar2
is
t number;
w int(3);
x int(3);
y int(3);
z int(3);

begin

t:= ip / 256;
w:= 256 * (t - FLOOR(t));
t:= (FLOOR (t))/ 256;
x:= 256 * (t - FLOOR(t));
t:= (FLOOR (t)) / 256;
y:= 256 * (t - FLOOR(t));
z:= FLOOR (t);

end int2ip;

Thank you very much,

Monica Roman

Monica Roman, May 10, 2004

2. ### Mark ClementsGuest

Monica Roman wrote:
> I've read a lot of the threads on this conversion but could not figure
> out which one is the correct function.
>
> I have never written PERL before, but I want to give it a try and be
> able to convert decimal numbers into IP addresses in the PERL script
> used to load the IPs plus other data into an Oracle database. Right
> now I use a SQL function within Oracle, but it slows down everything!

<snip horrific pl/sql> (yes, I know that that is its nature)

look at inet_ntoa in the Socket module for starters.

perldoc Socket

btw: it's written "Perl" or "perl".

regards,

Mark

Mark Clements, May 10, 2004

Monica Roman <> wrote:

> I've read a lot of the threads on this conversion but could not figure
> out which one is the correct function.

Have you tried the Perl FAQ?

> I have never written PERL before,

There is no PERL, there is only Perl and perl.

> Can someone help the translate into PERL the following SQL function?

Yes. _You_ can.

If you run into trouble post what you have so far and we will

> t:= ip / 256;
> w:= 256 * (t - FLOOR(t));

The assignment, division, multiplication and subtraction operators are
documented in:

perldoc perlop

The floor() function is a Question that is Asked Frequently:

perldoc -q floor

Does Perl have a round() function? What about ceil() and floor()?
Trig functions?

--
Perl programming
Fort Worth, Texas

4. ### John W. KrahnGuest

Monica Roman wrote:
>
> I've read a lot of the threads on this conversion but could not figure
> out which one is the correct function.
>
> I have never written PERL before, but I want to give it a try and be
> able to convert decimal numbers into IP addresses in the PERL script
> used to load the IPs plus other data into an Oracle database. Right
> now I use a SQL function within Oracle, but it slows down everything!
>
> Can someone help the translate into PERL the following SQL function?
>
> create or replace function int2ip(ip int)
> return varchar2
> is
> t number;
> w int(3);
> x int(3);
> y int(3);
> z int(3);
>
> begin
>
> t:= ip / 256;
> w:= 256 * (t - FLOOR(t));
> t:= (FLOOR (t))/ 256;
> x:= 256 * (t - FLOOR(t));
> t:= (FLOOR (t)) / 256;
> y:= 256 * (t - FLOOR(t));
> z:= FLOOR (t);
>
>
> end int2ip;

A direct Perl translation would be something like:

use POSIX qw( floor );

sub int2ip {
my \$ip = shift;

my \$t = \$ip / 256;
my \$w = 256 * ( \$t - floor \$t );
\$t = floor( \$t ) / 256;
my \$x = 256 * ( \$t - floor \$t );
\$t = floor( \$t ) / 256;
my \$y = 256 * ( \$t - floor \$t );
my \$z = floor \$t;

return "\$z.\$y.\$x.\$w";
}

However that is still relatively slow. A more Perlish solution would
be:

sub int2ip { join '.', unpack 'CCCC', pack 'N', \$_[ 0 ] }

Which is a lot faster. But an even faster solution would be:

use Socket;

sub int2ip { inet_ntoa inet_aton \$_[ 0 ] }

John
--
use Perl;
program
fulfillment

John W. Krahn, May 11, 2004
5. ### Anno SiegelGuest

John W. Krahn <> wrote in comp.lang.perl.misc:
> Monica Roman wrote:

[...]

> > Can someone help the translate into PERL the following SQL function?
> >
> > create or replace function int2ip(ip int)
> > return varchar2
> > is
> > t number;
> > w int(3);
> > x int(3);
> > y int(3);
> > z int(3);
> >
> > begin
> >
> > t:= ip / 256;
> > w:= 256 * (t - FLOOR(t));
> > t:= (FLOOR (t))/ 256;
> > x:= 256 * (t - FLOOR(t));
> > t:= (FLOOR (t)) / 256;
> > y:= 256 * (t - FLOOR(t));
> > z:= FLOOR (t);
> >
> >
> > end int2ip;

>
> A direct Perl translation would be something like:
>
> use POSIX qw( floor );
>
> sub int2ip {
> my \$ip = shift;
>
> my \$t = \$ip / 256;
> my \$w = 256 * ( \$t - floor \$t );
> \$t = floor( \$t ) / 256;
> my \$x = 256 * ( \$t - floor \$t );
> \$t = floor( \$t ) / 256;
> my \$y = 256 * ( \$t - floor \$t );
> my \$z = floor \$t;
>
> return "\$z.\$y.\$x.\$w";
> }

[snip other solutions]

That can be Perlified a bit (no critique, the OP asked for a direct
translation):

sub int2ip {
my \$ip = shift;
\$ip *= 256;
join '.', reverse map \$_ % 256, map \$ip = floor( \$ip/256), 1 .. 4;
}

I mention this because it shows a particular difficulty. The step

"map \$ip = floor( \$ip/256), 1 .. 4"

is meant to produce a list of iterative applications of "floor( \$ip/26)"
to \$ip. So it does, but the list starts with the operation applied
once to \$ip while we want the list to start with the original value of
\$ip (the operation applied zero times).

In the given case that could be corrected by multiplying \$ip with 256
first, but that's not always applicable, ugly and fragile.

Other possibilities are

map { my \$sav = \$ip; \$ip = floor( \$ip/256); \$sav} 1 .. 4;
or
map ( "\$ip", \$ip = floor( \$ip/256))[ 0], 1 .. 4;
or
( "\$ip", map \$ip = floor( \$ip/256), 2 .. 4);

but I can't say I like either very much. So currently I'd probably
write this

my @coll;
for ( 1 .. 4 ) {
push @coll, \$ip;
\$ip = floor( \$ip/256);
}

but I can't help thinking there must be a nice map solution.

Is there?

Anno

Anno Siegel, May 11, 2004
6. ### Monica RomanGuest

the options you gave me...nothing better than something tangible to
start learning Perl, a question with the answer, perfect. I have two
Perl books on my desk right now and I'm excited about learning it.

Thanks again,

Monica

Monica Roman, May 11, 2004