Home > Archive > PERL Beginners > July 2007 > Convert Scientific Notation to decimal equivalent
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Convert Scientific Notation to decimal equivalent
|
|
| Joseph L. Casale 2007-07-18, 6:59 pm |
| How can I detect this, I have been running some code for a few days to develop some files and ran into the situation where I am getting the following data for input:
14.95313 14.45312 0
14.95313 1.570813E-015 0
14.95313 -14.45313 0
-14.95313 -28.90625 0
-14.95313 -14.45313 0
-14.95313 1.570813E-015 0
-14.95313 14.45312 0
14.95313 -28.90625 0
0 -28.90625 0
-14.95313 28.90625 0
0 28.90625 0
14.95313 28.90625 0
And my code is skipping some lines as it checks for any erroneous data:
next if grep (/[^0-9.-]/, @data);
But that thinks the scientific notation is bad. I searched the net and didn't find anything. How can I match this specific pattern and convert it?
Thanks!
jlc
| |
| Chas Owens 2007-07-18, 6:59 pm |
| On 7/18/07, Joseph L. Casale <JCasale@activenetwerx.com> wrote:
> How can I detect this, I have been running some code for a few days to
> develop some files and ran into the situation where I am getting the
> following data for input:
>
> 14.95313 14.45312 0
> 14.95313 1.570813E-015 0
> 14.95313 -14.45313 0
> -14.95313 -28.90625 0
> -14.95313 -14.45313 0
> -14.95313 1.570813E-015 0
> -14.95313 14.45312 0
> 14.95313 -28.90625 0
> 0 -28.90625 0
> -14.95313 28.90625 0
> 0 28.90625 0
> 14.95313 28.90625 0
>
> And my code is skipping some lines as it checks for any erroneous data:
> next if grep (/[^0-9.-]/, @data);
> But that thinks the scientific notation is bad. I searched the net and
> didn't find anything. How can I match this specific pattern and convert it?
>
> Thanks!
> jlc
Don't write the regex yourself, use one of the ones in
Regexp::Common*. $RE{num}{real} is probably what you want.
As for how to make "1e3" into 1000, just add 0:
perl -e 'my $i = "1e3"; print $i, " ", $i+0, "\n"';
* http://search.cpan.org/~abigail/Reg...egexp/Common.pm
| |
| John W. Krahn 2007-07-18, 6:59 pm |
| Joseph L. Casale wrote:
> How can I detect this, I have been running some code for a few days to develop some files and ran into the situation where I am getting the following data for input:
>
> 14.95313 14.45312 0
> 14.95313 1.570813E-015 0
> 14.95313 -14.45313 0
> -14.95313 -28.90625 0
> -14.95313 -14.45313 0
> -14.95313 1.570813E-015 0
> -14.95313 14.45312 0
> 14.95313 -28.90625 0
> 0 -28.90625 0
> -14.95313 28.90625 0
> 0 28.90625 0
> 14.95313 28.90625 0
>
> And my code is skipping some lines as it checks for any erroneous data:
> next if grep (/[^0-9.-]/, @data);
> But that thinks the scientific notation is bad. I searched the net and didn't find anything. How can I match this specific pattern and convert it?
perldoc -q "How do I determine whether a scalar is a number"
John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
| |
| Xavier Noria 2007-07-18, 6:59 pm |
|
El Jul 18, 2007, a las 11:19 PM, Joseph L. Casale escribi=F3:
> How can I detect this, I have been running some code for a few days =20=
> to develop some files and ran into the situation where I am getting =20=
> the following data for input:
>
> 14.95313 14.45312 0
> 14.95313 1.570813E-015 0
> 14.95313 -14.45313 0
> -14.95313 -28.90625 0
> -14.95313 -14.45313 0
> -14.95313 1.570813E-015 0
> -14.95313 14.45312 0
> 14.95313 -28.90625 0
> 0 -28.90625 0
> -14.95313 28.90625 0
> 0 28.90625 0
> 14.95313 28.90625 0
>
> And my code is skipping some lines as it checks for any erroneous =20
> data:
> next if grep (/[^0-9.-]/, @data);
> But that thinks the scientific notation is bad. I searched the net =20
> and didn't find anything. How can I match this specific pattern and =20=
> convert it?
I am not sure I understand the problem to solve.
You need to filter out lines that contain something that's *not* a =20
number? If that's the case, is @data a split on whitespace for each =20
line? If that's the case in turn, have a look at
perldoc -q determine
or delegate the job to Regexp::Common:
$ perl -MRegexp::Common -wle 'print 1 if "1.570813E-015" =3D~ /\A$RE=20=
{num}{real}\z/'
1
-- fxn
| |
| Chas Owens 2007-07-18, 6:59 pm |
| On 7/18/07, Chas Owens <chas.owens@gmail.com> wrote:
> On 7/18/07, Joseph L. Casale <JCasale@activenetwerx.com> wrote:
>
> Don't write the regex yourself, use one of the ones in
> Regexp::Common*. $RE{num}{real} is probably what you want.
>
> As for how to make "1e3" into 1000, just add 0:
>
> perl -e 'my $i = "1e3"; print $i, " ", $i+0, "\n"';
>
>
> * http://search.cpan.org/~abigail/Reg...egexp/Common.pm
>
It is important to note that the print function* will use scientific
notation on numbers that are very large or very small. For instance
0.000000000000001570813 will be printed as "1.570813e-15". If you
absolutely must have 0.000000000000001570813 then you will need to use
printf or sprintf:
#!/usr/bin/perl
use strict;
use warnings;
my @n = (
0.000000000000001570813,
10000000000000000000000,
"1e4",
"1e-4"
);
for my $n (@n) {
my $s = expand($n);
print "$n is $s\n";
}
sub expand {
my $n = shift;
return $n unless $n =~ /^(.*)e([-+]?)(.*)$/;
my ($num, $sign, $exp) = ($1, $2, $3);
my $sig = $sign eq '-' ? "." . ($exp - 1 + length $num) : '';
return sprintf "%${sig}f", $n;
}
* actually any conversion of a number to string for very large or
small numbers, that is why the unless in expand works.
| |
| Chas Owens 2007-07-18, 6:59 pm |
| On 7/18/07, Joseph L. Casale <JCasale@activenetwerx.com> wrote:
> Interesting,
> I see from your regexp you use a \A and \z, from Perldoc this means:
> \A Match only at beginning of string
> \z Match only at end of string
Is "foo10bar" valid? /^$RE{num}{real}$/ says no, but /$RE{num}{real}/
says yes. \A and \z are similar to ^ and $, but are not effected by
the m and s flags (which is not an issue in your case since you are
splitting on whitespace).
>
> I am not sure I understand this requirement?
>
> In my case, I am checking an array of 3 scalars. Does this make sense:
> next unless @data =~ /$RE {num}{real}/;
> Does the regexp know to evaluate each element in the array implicitly?
> Or do I need to tell it this?
Not in Perl 5 (Perl 6 will have the smart match operator ~~). If you
want to bail if any of the values in @data are not numbers then you
should say
next if grep { not /^$RE{num}{real}$/ } @data;
Or if you want to reduce @data to just the numbers
next unless my @num = grep { /^$RE{num}{real}$/ } @data;
| |
| Chas Owens 2007-07-18, 9:59 pm |
| On 7/18/07, Joseph L. Casale <JCasale@activenetwerx.com> wrote:
> Chas,
> Sorry but I am not clear on what you mean by reduce? Do you mean
> remove all non numbers from the array?
snip
Sort of, the code doesn't modify the original array, it creates a new
array with only the values that are numbers.
| |
| Xavier Noria 2007-07-19, 7:59 am |
| El Jul 19, 2007, a las 12:19 AM, Joseph L. Casale escribi=F3:
> Interesting,
> I see from your regexp you use a \A and \z, from Perldoc this means:
> \A Match only at beginning of string
> \z Match only at end of string
>
> I am not sure I understand this requirement?
^ and $ depend on flags, and $ allows an optional trailing newline. =20
When I want to match a complete string exactly, I tend to use \A and =20
\z because they convey that intention clearly.
If your code processes line by line and splits on whitespace, \A ... =20
\z is equivalent to ^ ... $.
> In my case, I am checking an array of 3 scalars. Does this make sense:
> next unless @data =3D~ /$RE {num}{real}/;
> Does the regexp know to evaluate each element in the array =20
> implicitly? Or do I need to tell it this?
Detecting whether something holds in an array is the job of grep:
my $numbers =3D grep /\A$RE{num}{real}\z/, @data;
next unless $numbers =3D=3D @data;
-- fxn
| |
| Dr.Ruud 2007-07-21, 3:59 am |
| Xavier Noria schreef:
> Detecting whether something holds in an array is the job of grep:
>
> my $numbers = grep /\A$RE{num}{real}\z/, @data;
> next unless $numbers == @data;
Alternative:
die if grep !/\A$RE{num}{real}\z/, @data;
my $numbers = scalar @data;
--
Affijn, Ruud
"Gewoon is een tijger."
|
|
|
|
|