You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Tcl的expr命令会将实际非空的数值判定为空?

问题描述

我从无权限查看的未知来源导入了一组坐标数据,执行如下代码:

set yMin [lindex [lindex $bbox 0] 1]
puts "yMin: <$yMin>"

运行正常,输出如下(尖括号用于排查是否存在空格或隐藏制表符):

yMin: <-6.149999999999999e-02>

但问题在于,如果将yMin与任意数值(例如0.5)相乘,就会报错:

set Y2 [expr {0.5 * $yMin}]

can't use empty string as operand of "*"
while executing "expr {0.5 * $yMin}"
invoked from within "set Y2 [expr {0.5 * $yMin}]"

哪怕仅打印yMin的expr运算结果,也会报空操作数错误:

set Y1 [expr $yMin]
puts "Y1: <$Y1>"

empty expression in expression "" (parsing expression "")
invoked from within "expr $yMin"
invoked from within "set Y1 [expr $yMin]"

但有一个特殊测试结果:为expr添加花括号后运行正常:

set Y1 [expr {$yMin}]
puts "Y1: <$Y1>"

Y1: <-0.06149999999999999>


问题复现尝试

感谢Glenn Jackman提供的测试模板,但如下代码无法复现问题,这也是发帖求助的原因:

% set bbox {{-4.599999999999999e-02 -6.149999999999999e-02} {8.000000000000002e-02 6.149999999999999e-02}}
{-4.599999999999999e-02 -6.149999999999999e-02} {8.000000000000002e-02 6.149999999999999e-02}
% set yMin [lindex [lindex $bbox 0] 1]
-6.149999999999999e-02
% expr {1 + $yMin}
0.9385

排查尝试

首先验证yMin是否为空,结果显示非空:

if {$yMin eq {}} {
    puts "Empty records"
    exit 1 
} else {
    puts "yMin is not empty: <$yMin>"
}

yMin is not empty: <-6.149999999999999e-02>

之后我尝试用trim、map、regsub移除所有空格和制表符,处理后打印的结果仍正常,但运算依旧报错:

set trim_yMin [string trim $yMin]
puts "trim_yMin: <$trim_yMin>"

set map_yMin [string map {" " ""} $yMin]
puts "map_yMin: <$map_yMin>"

regsub -all {\s} $yMin {} reg_yMin
puts "reg_yMin: <$reg_yMin>"

if {$trim_yMin eq {} || $map_yMin eq {} || $reg_yMin eq {}} {
    puts "Empty records"
    exit 1
} else {
    puts "trim_yMin is not empty: <$reg_yMin>"
    puts "map_yMin is not empty: <$reg_yMin>"
    puts "reg_yMin is not empty: <$reg_yMin>"
}

trim_yMin: <-6.149999999999999e-02>
map_yMin: <-6.149999999999999e-02>
reg_yMin: <-6.149999999999999e-02>
trim_yMin is not empty: <-6.149999999999999e-02>
map_yMin is not empty: <-6.149999999999999e-02>
reg_yMin is not empty: <-6.149999999999999e-02>

处理后的值运算依旧报错:

set reg_Y2 [expr {0.5 * $reg_yMin}]
puts "0.5 * reg_yMin: $reg_Y2"

can't use empty string as operand of "*"
while executing "expr {0.5 * $reg_yMin}"
invoked from within "set reg_Y2 [expr {0.5 * $reg_yMin}]"


补充排查与回复

回复Ergwun的测试建议,执行代码如下:

puts $bbox;
set yMin [lindex [lindex $bbox 0] 1]
puts "yMin: <$yMin>"

{-4.599999999999999e-02 -6.149999999999999e-02} {8.000000000000002e-02 6.149999999999999e-02}
yMin: <-6.149999999999999e-02>

set Y2 [expr {0.5 * $yMin}]
puts $Y2

can't use empty string as operand of "*"
while executing "expr {0.5 * $yMin}"
invoked from within "set Y2 [expr {0.5 * $yMin}]"

回复benaja的建议,查看变量表示:

puts [tcl::unsupported::representation $yMin]

value is a string with a refcount of 4, object pointer at 0x44ed0910, internal representation 0x450d6120:(nil), string representation "-6.14999999999...."

回复Shawn的建议,执行测试:

puts [tcl::unsupported::representation $yMin]
puts [binary encode hex $yMin]
puts [tcl::unsupported::representation $yMin]
puts [string is double -strict $yMin]
puts [tcl::unsupported::representation $yMin]

value is a string with a refcount of 4, object pointer at 0x44ed6030, internal representation 0x450de4b0:(nil), string representation "-6.1499999999..."

2d362e313439393939393939393939393939652d3032

value is a bytearray with a refcount of 4, object pointer at 0x44ed6030, internal representation 0x44ee0dc0:(nil), string representation "-6.1499999999..."

1

value is a double with a refcount of 4, object pointer at 0x44ed6030, internal representation 0xbfaf7ced916872af:(nil), string representation "-6.1499999999..."

直接使用字面量运算正常:

set Y2 [expr {0.5 * -6.149999999999999e-02}]
puts "Y2: $Y2"
set new_Y2 [expr {0.5*-6.149999999999999e-02}]
puts "new_Y2: $new_Y2"

Y2: -0.030749999999999996
new_Y2: -0.030749999999999996

回复Schelte Bron的建议,给变量前加空格后报错类型变化:

puts [tcl::unsupported::representation $yMin]
set yMin " $yMin"
puts [tcl::unsupported::representation $yMin]
set Y2 [expr {0.5 * $yMin}]
puts $Y2

value is a string with a refcount of 4, object pointer at 0x44ec28a0, internal representation 0x450be540:(nil), string representation "-6.1499999999..."

value is a string with a refcount of 2, object pointer at 0x446bbc70, internal representation 0x44695fd0:(nil), string representation " -6.149999999..."

can't use non-numeric string as operand of "*"
while executing "expr {0.5 * $yMin}"
invoked from within
"set Y2 [expr {0.5 * $yMin}]"

按照建议做二进制编解码往返后运算依旧报错:

puts "Is yMin double? : [string is double -strict $yMin]"
set binary_yMin [binary encode hex $yMin]
set double_binary_yMin [binary decode hex $binary_yMin]
puts "yMin: $yMin"
puts "Binary of double yMin: $binary_yMin"
puts "Double binary double: $double_binary_yMin"
set Y2 [expr {0.5 * $double_binary_yMin}]
puts $Y2

Is yMin double? : 1
yMin: -6.149999999999999e-02
Binary of double yMin: 2d362e313439393939393939393939393939652d3032
Double binary double: -6.149999999999999e-02
can't use empty string as operand of "*"
while executing "expr {0.5 * $double_binary_yMin}"
invoked from within "set Y2 [expr {0.5 * $double_binary_yMin}]"

使用tcl::mathop::*运算同样报错:

puts [tcl::mathop::* 0.5 $yMin]

can't use empty string as operand of "*"
while executing
"tcl::mathop::* 0.5 $yMin"
invoked from within
"puts [tcl::mathop::* 0.5 $yMin]"

已尝试所有能想到的排查手段仍无法解决问题,恳请各位提供解决思路,非常感谢。


内容的提问来源于stack exchange,提问作者Zureas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:57:03