Error with floating point / scientific notation values in bash - linux

I have a problem with the following piece of code
THRESH_SERIE=("1" "5E-1" "1E-1" "5E-2" "1E-2" "5E-3" "1E-3" "5E-4" "1E-4")
for ((i=0;i<${#THRESH_SERIE[#]};i++))
do
let thresh=$(echo ${THRESH_SERIE[$i]})
$EXEC 1 $N ${thresh} 0 0 >> $OUTPUT
done
If I try to run the script it will return an error like the following for each value in the array:
/bench_new.sh: line 40: let: thresh=5E: value too great for base (error token is "5E")
I've tried also to use floating point numbers (like "0.1"), but it gives a different error. How can I solve this?

No particular reason for the array here (other than they're "fun" to play with):
THRESH_SERIE="1 5E-1 1E-1 5E-2 1E-2 5E-3 1E-3 5E-4 1E-4"
for thresh in ${THRESH_SERIE}
do
$EXEC 1 $N ${thresh} 0 0 >> $OUTPUT
done

The reason this is borking is that let treats all it's arguments as arithmetic values.
bash Arithmetic expression are defined by a set of rules which default to decimal. the E is not a decimal number and hence the error.
as #DiegoBasch suggests try dropping the let so it's not treated as an arithmetic expression.

Related

Python- Invalid Syntax error

I'm getting an invalid syntax error in the final variable. I don't see what the problem is, I think my indentation is correct, can tell me what I am doing wrong? I'm trying to make a simple python xor program.
msg='To use this decimal to binary converter tool, you should type a decimal value like 308 into the left field below, and then hit the Convert button. This way you can convert up to 19 decimal characters (max. value of 9223372036854775807) to binary value.'
key='ab'
encrypt=[]
decrypt=[]
count=0
for i in msg:
if count>=len(key):
count=0
encrypt.append(ord(i)^ord(key[count]))
count+=1
count=0
print(encrypt)
for i in encrypt:
if count>=len(key):
count=0
count+=1
decrypt.append(i^ord(key[count])
final=''.join(chr(e) for e in decrypt)
print(final)
Whenever you see dubious error messages in places that don't make sense, count your parentheses!
In you case, you missed a closing parentheses when calling the ord function:
decrypt.append(i ^ ord(key[count]))

Comparison between strings and integers in matlab

I am doing some classification and needed to convert an integer code to strings for that reason. I wrote something like this:
s(1).class = 1;
s(2).class = 7;
s(3).class = 9;
[s([find([s.class] == 1)]).class] = deal('c1'); %first conversion
[s([find([s.class] > 1)]).class] = deal('c2'); %second conversion
and was surprised to find s being a 1x4 struct array after the second conversion instead of the expected 1x3 struct array with the values.
Now, after some research, I understand that after the first conversion the value of s(1).class is 'c1' and the argument to find in the second conversion is not what I assumed it would be. The [s.class] statement actually returns something like the string 'c1\a\t' with ASCII escape sequences for bell and horizontal tab.
As the comparison does work (returning the matrix [1 1 1 1] and thus expanding my structure) I assume that matlab converts either the operand [s.class] or the operand 1.
Which is it? What actually is compared here numbers or characters?
And on the other hand is there a built in way to make > more restrictive, i. e. to require the operands to be of the same type and if not to throw an error?
When you do the comparison 'ab' > 1, the char array 'ab' gets converted to a double array, namely the ASCII codes of the characters. So 'ab' > 1 is equivalent to double('ab') > 1, which gives [1 1].
To get the behaviour you want (issue an error if one of the arguments is char) you could define a function:
function z = greaterthan(x,y)
if ischar(x) || ischar(y)
error('Invalid comparison: one of the input arguments is of type char')
else
z = x>y;
end
so that
>> greaterthan([0 1 2], 1)
ans =
0 0 1
>> greaterthan('ab', 1)
??? Error using ==> greaterthan at 3
Invalid comparison between char and int
Because you have not provided any expected output yet, I am going with the observations.
You are using a comprehension method (by invoking find) to determine which locations you will be populating for struct s with the results from your method deal (takes the argument c1 and c2). You have already set your type for s{whatever).class in the first snippet you provided. Which means it is number you are comparing, not character.
There is this isa function to see which class your variable belongs to. Use that to see what it is you are actually putting in (should say int32 for your case).

Getting precision of a float in Perl?

Let's say I had a Perl variable:
my $string = "40.23";
my $convert_to_num = $string * 1;
Is there a way I can find the precision of this float value? My solution so far was to simply just loop through the string, find the first instance of '.', and just start counting how many decimal places, returning 2 in this case. I'm just wondering if there was a more elegant or built-in function for this sort of thing. Thanks!
Here is an answer for "number of things after the period" in $nstring
length(($nstring =~ /\.(.*)/)[0]);
The matching part first finds . (\.), then matches everything else (.*). Since .* is in parentheses, it is returned as the first array element ([0]). Then I count how many with the length() function.
Anything you do in Perl with plain variables will be dependent on the compiler and hardware you use. If you really care about the precision, use
use "Math::BigFloat";
And set the desired properties. The number of digits is more properly termed accuracy in Math::BigFloat.
use Math::BigFloat;
Math::BigFloat->accuracy(12);
$n = new Math::BigFloat "52.12";
print "Accuracy of $n is ", $n->accuracy(), " length ",scalar($n->length()),"\n";
Will return
Accuracy of 52.1200000000 is 12 length 4

Perl compare operators and stringified "numbers"

I've been working a lot lately with perl, still I dont really know how <,>,>=,=<, ne,gt, etc.. on stringified "numbers", by "number" I mean something like: '1.4.5.6.7.8.0'
correct me If I'm wrong, the following returns true:
if ('1.4.5' > '8.7.8');
because both will be coerced to true (not an empty string).
but, how does ne,gt,etc string operators work on such numbers?
basically I'm trying to compare version numbers consisted of the following form:
1.3.4.0.2
I can make a numerical comparison of each digit, but before, I ranther want to know of the
string comparing operators perform on such strings.
Thanks,
First: Please use warnings all the time. You would have realized the following at once:
$ perl -wle 'print 1 unless "1.4.5" > "8.7.8"'
Argument "8.7.8" isn't numeric in numeric gt (>) at -e line 1.
Argument "1.4.5" isn't numeric in numeric gt (>) at -e line 1.
Perl v5.9.0 came distributed with version. And this module makes it very easy to compare version numbers:
use warnings;
use version;
my ($small, $large) = (version->parse('1.4.5'), version->parse('8.7.8'));
print "larger\n" if $small > $large;
print "smaller\n" if $small < $large;
A string comparison will only work if every number between the dots has the same length. A string comparison has no knowledge of number and will begin to compare dots and digits (as they are both characters in a string).
There a CPAN module that does exactly what you are looking for: Sort::Versions
When you compare strings using numerical relation operators <, >, etc., Perl issues a warning if you use warnings. However, Perl will still attempt to convert the strings into numbers. If the string starts with digits, Perl will use these, otherwise the string equates to 0. In your example comparing '1.4.5' and '8.7.8' has the same effect as comparing numbers 1.4 and 8.7.
But for ne, gt, etc. it really doesn't matter if your strings consist of numbers or anything else (including dots). Therefore:
print "greater" if '2.3.4' gt '10.1.2' # prints 'greater' because '2' > '1' stringwise
print "greater" if '02.3.4' gt '10.1.2' # prints nothing because '0' < '1' stringwise
Therefore you cannot use neither >, <, etc. nor gt, lt, etc. for version comparison, you have to choose different approach, as proposed in another answers, for example.
Not sure on the overhead of this, but you might try Sort::Naturally. And particularly, the ncmp operator.
As #tent pointed out, #SebastianStumpf's solution is close, but not quite right because:
>perl -Mversion -e 'my #n = ( "1.10", "1.9" ); print "$n[0] is " . ( version->parse($n[0]) > version->parse($n[1]) ? "larger" : "smaller" ) . " than $n[1]\n";'
1.10 is smaller than 1.9
Luckily this is easily solved following the hint in version's documentation:
The leading 'v' is now strongly recommended for clarity, and will
throw a warning in a future release if omitted.
>perl -Mversion -e 'my #n = ( "1.10", "1.9" ); print "$n[0] is " . ( version->parse("v$n[0]") > version->parse("v$n[1]") ? "larger" : "smaller" ) . " than $n[1]\n";'
1.10 is larger than 1.9

Haskell: lexical error in string/character literal at character 'i'

I'm fairly new to Haskell programming and I'm having trouble understanding why I'm receiving this error in my code.
My problem is as follows: Any positive integer i can be expressed as i = 2^n*k, where k is odd, that is, as a power of 2 times an odd number. We call n the exponent of 2 in i. For example, the exponent of 2 in 40 is 3 (because 40 = 2^3*5) whereas the exponent of 2 in 42 is 1. If i itself is odd, then n is zero. If, on the other hand, i is even, that means it can be divided by 2. Write a function exponentOfTwo for finding the exponent of 2 in its argument.
I understand the psuedocode and it seems fairly simple: recursively divide i by 2 until result is odd, the number of times the division happens is n
here is my code (line 31-32):
exponentOfTwo :: Int -> Int
exponentOfTwo i = if odd i then 0 else 1 + exponentOfTwo (i 'div' 2)
I'm receiving the error "lexical error in string/character literal at character 'i'" on line 32 column 62.
I've tried searching for a solution to this error everywhere and so far I've had no luck.
To use a function in infix for, surround it with backticks (`), not with single quotes ('). The latter are for character literals, which, well are only one character long.
Are the characters around div backquotes rather than normal quotes? They need to be to allow a function name to be used as an infix operator. I changed that in your definition and the code worked for me.

Resources