Comparing floating point with another number [closed] - perl

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
How to check if one floating point number is bigger than another number in Perl?
i.e: 100.4 > 90
I tried to work with use POSIX, rounding the 100.4 to 101.0 and converting both of them with int, but Perl still thinks that my 100.4 is smaller than my 90.
Edit: The bug was somewhere else. The privious code returned me sometimes true and sometimes false.

No, Perl doesn't 'think' that, and that's easy to check:
print 100.4 > 90 ? 'Greater' : 'Lesser'; # Greater
My (wild) guess is that you've tried to sort an array of floats, and got 100.4 standing before 90. For example, like this:
my #floats = (100.4, 50, 9);
print $_, "\n" for sort #floats;
# 100.4
# 50
# 9
The catch is that by default Perl uses string comparison in sort. So both 100.4 and 90 are cast to string first, and '100.4' is indeed lesser than '9', because '1' is lesser than '9' (strings are compared char-by-char).
The solution is simple: override the sorting routine when dealing with numbers.
print $_, "\n" for sort { $a <=> $b } #floats;
# 9
# 50
# 100.4

Related

Powershell, what exactly does each part of this code do? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
$a = gc "$home\documents\textfile.txt"
for ($i = 0; $i -lt $a.Count + 1; $i++)
{
$a[($a.count-1) - $i]
}
I know the first line gets the content of the text file, and the file is shown from bottom to top, but what exactly is the for loop doing step-by-step?
The for loop sets $i to 0, loops for as long as it's less than or equal to $a.Count-1 and increments after each iteration.
$a.Count is the total number of lines in the file, so $a.Count-1 is the final element (line) of $a which is an array indexed from zero.
Within each iteration $i gets larger and so the line inside the loop returns the value held at the last element minus $i.
If $a has 5 lines for example, then there are 5 elements in $a. These are $a[0] to $a[4]
On the first iteration $i is zero so the value within the square brackets evaluates to 5-1-0 = 4. This gives the last line.
On the second iteration all that changes is $i is incremented. This evaluates to 5-1-1 = 3. This is the second to last line.
This carries on until $i = 4 (which is $a.Count-1) and the code evaluates 5-1-4=0, which results in the first element of $a being output.
Hope that makes sense enough for you...
What the for loop is doing is getting the index of the string provided by $a.
You can play with indexing by setting a variable equal to a string or array, and looking at each of the indices within it. Take, for example, $x = "this is a string". You can then look at $x[n] where n is an integer, and it will show you what that index in the string or array contains. For $x[0] Powershell would return "t", or if $x were an array of strings it would return "this".
Now that we know what indexing is, we can look at the math operators within your for loop. To think about this in the way that Powershell is processing it, we'll work from the parenthesis out. $a.count returns a value equal to the number of objects contained in $a. If we look at what Get-Content returns (with help from our handy Get-Help gc), we can see that it is returning an object per line contained in that file.
When we apply these principles to the script you provided, we can determine that the script will return the lines of the file in reverse order.

"isn't numeric" warning from perl [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Perl keeps telling me that '11' from my input file is not numeric. Last time I checked 11 was a number, so I'm a bit confused what the problem is here and hence where to start looking.
Interestingly, it's line 1 of my input file causing the problem, the numbers on lines 2 onwards are interpreted correctly.
Argument "11" isn't numeric in numeric eq (==) at ./extract.pl line 200, <INPUTFILE> line 1.
Line 200 is
if ($_data[0] == $_ch && !exists $_ch_sn{$_data[1]}) { $_ch_sn{$_data[1]} = undef; }
Any help much appreciated!
The error was caused by a BOM in my inputfile. Using setlocal nobomb in Vi solved the problem!
It could be that the source doesn't actually contain 11 (e.g. maybe it contains a character that resembles a one but isn't), but I suspect the warning message is incorrectly identifying the expression that's non-numeric[1].
That fact that nothing remotely resembling 11 appears on that line appears to support that[2].
So just pretend you obtained the following warning:
Argument isn't numeric in numeric eq (==) at ./extract.pl line 200, <INPUTFILE> line 1.
This means that $_data[0] or $_ch is a non-numeric string[2].
If both should be numbers, determine which one isn't, possibly using the following code:
use Data::Dumper; { local $Data::Dumper::Useqq = 1; warn(Dumper($_data[0], $_ch)); }
Once you determine which variable is wrong, debug to find out why it is that way.
If they could be legitimately be non-numeric, add appropriate checks to handle that situation.
For performance reasons, that part of the error message is deduced from the compiled code, a complicated and unreliable process.
I'm assuming the if has no elsif clause. Warnings from an elsif condition can appear to be from an if statement.

Why does this not give the 2nd last element of the array? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
print $some_array[$#some_array - 1];
My intuitive understanding is the above code should print the 2nd last element in #some_array.
However in reality it does not. It prints something I cannot made sense of.
It does print the second to last element in the array:
my #nums = qw(a b c d e);
print "$nums[$#nums-1]\n"; # prints 'd'
Here, $#nums gives the last index of an array (in this case 4 - arrays are zero-based), and hence $#nums - 1 gives array element 3.
A more common way of writing this would be:
$array[-2]
The behavior of $some_array[$#some_array - 1] depends on how many elements #some_array has.
If #some_array has 2 or more elements (scalar #array >= 2, or equivalently $#array >= 1), then your statement:
print $some_array[$#some_array - 1];
should work correctly. Say the array has 10 elements, then $#some_array == 9, and you'll print $some_array[8], the second-to-last element.
If #some_array has just one element, then $#some_array == 0, and you'll print the "-1th" element. Negative array indices are treated specially: -1 gives you the last element of the array, -2 the second-to-last, and so forth. And if your goal is to print the second-to-last element of the array, you should be using this feature.
If #some_array is empty (scalar #some_array == 0, $#some_array == -1), then your statement will try to print $some_array[-2], which doesn't exist, resulting in an error message.

Print a substring of an array value [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have an array in the third element dataArr[2], I know it contains a 10 digit phone. I need to only read or print the first 6 digits. For instance if my phone is 8329001111, I need to print out the 832900. I tried to see if I can use substr but I keep reading or printing the full list. Do I need to dereference..
Try this :
$dataArr[2] =~ s/\s//g; # ensure there's no spaces
print substr($dataArr[2], 0, 6);
# ^ ^ ^
# variable | |
# offset start|
# |
# substring length

Float comparison issues in Perl [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How do I fix this Perl code so that 1.1 + 2.2 == 3.3?
I'm working on a Perl script that compares strings representing gene models and prints out a summary of the comparison. If the gene models match perfectly, I print out a very terse summary, but if they are different, the summary is quite verbose.
The script looks at the value of a variable to determine whether it should do the terse or verbose summary--if the variable is equal to 1, it should print the terse summary; otherwise, it should print the verbose summary.
Since the value is numeric (a float), I've been using the == operator to do the comparison.
if($stats->{overall_simple_matching_coefficient} == 1)
{
print "Gene structures match perfectly!\n";
}
This worked correctly for all of my tests and even for most of the new cases I am running now, but I found a weird case where the value was equal to 1 but the above comparison failed. I have not been able to figure out why the comparison failed, and stranger yet, when I changed the == operator to the eq operator, it seemed to work fine.
I thought the == was for numerical comparison and eq was for string comparison. Am I missing something here?
Update: If I print out the value right before the comparison...
printf("Test: '%f', '%d', '%s'\n", $stats->{overall_simple_matching_coefficient}, $stats->{overall_simple_matching_coefficient}, $stats->{overall_simple_matching_coefficient});
...I get this.
Test: '1.000000', '0', '1'
The first thing any computer language teacher should teach you about any computer language is that YOU CANNOT COMPARE FLOATS FOR EQUALITY. This is true of any language. Floating point arithmetic is not exact, and two floats that look like they're the same will be different in the insignificant digits somewhere where you can't see it. Instead, you can only compare that they are close to each other - like
if (abs(stats->{overall_simple_matching_coefficient)-1) < 0.0001)
What do you get if you print the value of $stats->{overall_simple_matching_coefficient} just before the comparison? If it's 1, try printf with a format of "%20.10f". I strongly suspect you have some rounding error (less then 1e-6) accumulated in the variable and it's not comparing equal numerically. However when converted to string, since the error is right of the 6th decimal place, and the default string format is to six places, it compares equal.