简体   繁体   English

浮点比较问题

[英]Problem with floating point comparison

I am trying to check if a value I read from a text file is zero: 我正在尝试检查从文本文件读取的值是否为零:

[[ $(echo $line | cut -d" " -f5) -gt 0 ]] && [[ $(echo $line | cut -d" " -f7 | bc -l) -eq 0 ]]

With the first condition there is no problem because f5 are integers. 对于第一个条件,因为f5是整数,所以没有问题。 The problem comes form the second condition. 问题来自第二个条件。 I receive this error message: 我收到此错误消息:

[[: 1.235: syntax error: invalid arithmetic operator (error token is ".235")

I have tried several suggestions I found in different forums such as using echo $line | cut -d" " -f7 | bc -l 我尝试了在不同论坛中找到的一些建议,例如使用echo $line | cut -d" " -f7 | bc -l echo $line | cut -d" " -f7 | bc -l echo $line | cut -d" " -f7 | bc -l with and without double quotes, etc. However, the error persist. echo $line | cut -d" " -f7 | bc -l带和不带双引号等。但是,错误仍然存​​在。 f7 is a positive number and is given with 3 decimal places. f7是一个正数,并给出3个小数位。 Removing decimals or approximating is not an option because I need the result to be exactly zero (0.000). 删除小数点或近似值是不可行的,因为我需要结果精确为零(0.000)。

Generally, you can't compare floating-point numbers for equality. 通常,您无法比较浮点数是否相等。 This is because the binary representation of decimal numbers is not precise and you get rounding errors. 这是因为十进制数字的二进制表示形式不精确,并且会出现舍入错误。 This is the standard answer that most others will give you. 这是大多数其他人会给您的标准答案。

In this specific case, you don't actually need to compare floating-point numbers, because you're just testing whether some text represents a specific number. 在这种特定情况下,您实际上不需要比较浮点数,因为您只是在测试某些文本是否代表特定数字。 Since you're in shell, you can either use a regular string compare against "0.000" - assuming your data is rounded in that way - or using regular expressions with grep/egrep. 由于您在shell中,因此可以将正则字符串与“ 0.000”进行比较-假设您的数据以这种方式进行了四舍五入-或使用带有grep / egrep的正则表达式。 Something like 就像是

egrep -q '0(|\.0+)'

Will match 0, 0.0, 0.00, etc, and will exit indicating success or failure, which you can use in the surrounding if statement: 将匹配0、0.0、0.00等,并退出以指示成功或失败,您可以在周围的if语句中使用它:

if cut and pipe soup | egrep ... ; then
  ...
fi

Use a string comparison instead. 请使用字符串比较。 Replace: 更换:

-eq 0

with: 与:

= '0.000'

TZ: TZ:

Script section from comment: 注释中的脚本部分:

for clus in $(ls *.cluster) ; do
    while read line ; do
        if [[ $(echo $line | cut -d" " -f11) -gt 0 ]] && [[ "$(echo $line | cut -d" " -f15 | bc -l)" = '0.000' ]] ; then
            cat $(echo $line | cut -d" " -f6).pdb >> test/$(echo $line | cut -d" " -f2)_pisa.pdb
        fi
    done < $clus
done

My pseudo-Python interpretation: 我的伪Python解释:

for clus in *.cluster:
    for line in clus:
        fields = line.split(' ')
        # field numbers are counting from 1 as in cut
        if int(field 11) > 0 and str(field 15) == '0.000':
            fin_name = (field 6) + '.pdb'
            fout_name = (field 2) + '_pisa.pdb'
            cat fin_name >> fout_name

Is that what you intended? 那是你想要的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM