i have the following problem:
I have a number of values x and I need to compute x^e (e being euler's number).
I do this:
$x = $x ** exp(1);
This results in "nan" for all of my test cases.
However if I print the values of $x before I do this and then take one and change above line to this:
$x = -12.4061063212051 ** exp(1);
it results in perfectly fine numbers.
Can anyone point out what I am doing wrong here?
Thanks
PS: Maybe the error hides somewhere else, so here is how i compute $x:
$y = #some float value taken from the output string of another program
$x = ($y/(303 * 0.0019872041));
print $x; #prints number
$x = $x ** exp(1);
print $x; #prints "nan"
It's all about operator precedence:
$x = -12.4061063212051 ** exp(1);
is really
$x = - (12.4061063212051 ** exp(1));
as seen using
$ perl -MO=Deparse,-p -e'$x = -12.4061063212051 ** $e'
($x = (-(12.4061063212051 ** $e)));
-e syntax OK
Which is fine.
If you try the following it will also fail just as your program:
$x = (- 12.4061063212051) ** exp(1);
And it should, there is no real number that meets this criteria.
Let's make things a bit easier for the moment, and suppose that we were taking $x**2.5. Well, since 2.5==5.0/2.0, we have $x**2.5==$x**(5.0/2.0)==($x**0.5)**5.0. Or, in other words, $x**2.5 is the same thing as the fifth power of sqrt($x).
Since computers tend to only deal with real numbers by default, what do you think would happen if, say $x==-1?
Yeah....now, what if $x<0$ and we wanted to take $x**exp(1) (the decimal approximation that Perl uses for exp(1) is 2.71828182845905)?
Related
I tried the following in a Perl script:
$b = 19999999999999999 % 10000000000000000;
print "$b\n";
It incorrectly outputted 0.
Then I found an answer saying to use bignum:
use bignum;
$b = 19999999999999999 % 10000000000000000;
print "$b\n";
It correctly outputted 9999999999999999.
But bignum just converts all integer constants into a Math::BigInt. So I tried the following which should be the same as using bignum:
use Math::BigInt;
$b = Math::BigInt->new(19999999999999999) % Math::BigInt->new(10000000000000000);
print "$b\n";
But that incorrectly outputted 0. Am I doing something wrong with Math::BigInt?
You're still using native Perl numbers first and then converting them to Math::BigInt objects. Try this instead:
my $x = Math::BigInt->new('19999999999999999') % Math::BigInt->new('10000000000000000');
Quoting from perldoc Math::BigInt:
Input given as scalar numbers might lose precision. Quote your input to ensure that no digits are lost:
$x = Math::BigInt->new( 56789012345678901234 ); # bad
$x = Math::BigInt->new('56789012345678901234'); # good
(Also, don't use $b outside of sort and similar routines.)
I'm trying to make a program that calculates the factorial of a number. I'm not very familiar with perl, so I think I'm missing some grammar rule.
When I enter 5 the program should return 120. Instead it returns a few dozen 1's. When I try other numbers I still get 1's, but more or less of them depending on if I enter a higher or lower number.
Here's my code:
print"enter a positive # more than 0: \n";
$num = <STDIN>;
$fact = 1;
while($num>1)
(
$fact = $fact x $num;
$num = $num - 1;
)
print $fact;
system("pause");
This is my first post to stack Overflow, so I hope I obeyed all theposting rules.
The problem is this line:
$fact = $fact x $num;
x is not the multiplication operator in Perl. It is used to repeat things. 1 x 5 will produce "11111".
Instead you want *.
$fact = $fact * $num;
Which can be written using *=.
$fact *= $num;
A few other issues...
Get used to strict and warnings now. By default, Perl will let you use variables without declaring them. They are global, which is bad for reasons you'll learn later. Right now it means if you have a typo in a variable name like $face Perl won't tell you about it.
Looping over a list of numbers is better done with a for loop over a range using ...
# Loop from 1 to $num setting $factor each time.
for my $factor (1..$num) {
$fact *= $factor;
}
Instead of using a system call to pause the program, use sleep.
In Perl I know that we can use "$x *= $n" for multiplying x with n. So I mistakenly used "**=" and output seemed to be very high number for very small values of "n". What does that operator do ?
Please do not say that it is just for exponential. It is not. please verify using the syntax I have shown
It is the exponentiation operator:
perl -e 'print 2**3';
prints 8
So, $a **= n is equivalent to $a = $a**n which is equivalent with $a raised to the power n
While using scalar values in perl, I am not able to accomplish the desired results. Need your help in figuring where I am going wrong..
Say I want to loop 9 times and print 0.1 to 0.9
I declared variable $i and using it in for loop as well as inside the loop.
for($i = 1; $i < 10; $i++)
{
$b = $ie-01; # (This where I go wrong, I am not sure If I am following correct
# syntax here, Because I see -1 getting printed instead of $i value
# which is incremented on each loop)
print "The value now is: $b\n";
}
I do know of different ways to get the desired result but I wanna know how to use exponent to get the desired output. . . . .
Why $i is treated as 0 when used in conjunction with e?
I think you only forgot to include the multiplication operator *:
$i * 1e-01
The string $ie-01 will be interpreted as $ie - 01 which is an unititialized variable (i.e. zero) minus one which will give you -1. (You can use the e-notation only with constant numbers but not with variables.)
Your first mistake was not including:
use strict;
use warnings;
This would have told you about the variable $ie not being declared.
There is no reasonable way to make ${i}e-01 work; you would have to eval it, which is not reasonable. The standard way to write it would be:
$b = $i * 0.1;
I know that there is a library that do that
use Scalar::Util qw(looks_like_number);
yet I want to do it using perl regular expression. And I want it to work for double numbers not for only integers.
so I want something better than this
$var =~ /^[+-]?\d+$/
thanks.
Constructing a single regular expression to validate a number is really difficult. There simply are too many criteria to consider. Perlfaq4 contains a section "How do I determine whether a scalar is a number/whole/integer/float?
The code from that documentation shows the following tests:
if (/\D/) {print "has nondigits\n" }
if (/^\d+$/) {print "is a whole number\n" }
if (/^-?\d+$/) {print "is an integer\n" }
if (/^[+-]?\d+$/) {print "is a +/- integer\n" }
if (/^-?\d+\.?\d*$/) {print "is a real number\n" }
if (/^-?(?:\d+(?:\.\d*)?|\.\d+)$/) {print "is a decimal number\n"}
if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) {
print "is a C float\n"
}
The first test disqualifies an unsigned integer.
The second test qualifies a whole number.
The third test qualifies an integer.
The fourth test qualifies a positive/negatively signed integer.
The fifth test qualifies a real number.
The sixth test qualifies a decimal number.
The seventh test qualifies a number in c-style scientific notation.
So if you were using those tests (excluding the first one) you would have to verify that one or more of the tests passes. Then you've got a number.
Another method, since you don't want to use the module Scalar::Util, you can learn from the code IN Scalar::Util. The looks_like_number() function is set up like this:
sub looks_like_number {
local $_ = shift;
# checks from perlfaq4
return $] < 5.009002 unless defined;
return 1 if (/^[+-]?\d+$/); # is a +/- integer
return 1 if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/); # a C float
return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i)
or ($] >= 5.006001 and /^Inf$/i);
0;
}
You should be able to use the portions of that function that are applicable to your situation.
I would like to point out, however, that Scalar::Util is a core Perl module; it ships with Perl, just like strict does. The best practice of all is probably to just use it.
You should use Regexp::Common, most patterns are more complicated than you realize.
use Regexp::Common;
my $real = 3.14159;
print "Real" if $real =~ /$RE{num}{real}/;
However, the pattern is not anchored by default, so a stricter version is:
my $real_pat = $RE{num}{real};
my $real = 3.14159;
print "Real" if $real =~ /^$real_pat$/;
Well first you should make sure that the number does not contain any commas so you do this:
$var =~ s/,//g; # remove all the commas
Then create another variable to do the rest of the compare.
$var2=$var;
Then remove the . from the new variable yet only once occurrence.
$var2 =~ s/.//; # replace . with nothing to compare yet only once.
now var2 should look like an integer with no "."
so do this:
if($var2 !~ /^[+-]?\d+$/){
print "not valid";
}else{
#use var1
}
you can fix this code and write it as a function if you need to use it more than once.
Cheers!