3

问题陈述

我正在从未知来源导入一组坐标,我无权查看。

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

它工作正常。

yMin:<-6.149999999999999e-02>

括号用于检查是否有任何空格甚至隐藏的选项卡。但是,如果yMin乘以任何数字,例如 0.5,就会出错。

set Y2 [expr {0.5 * $yMin}]


在执行
从“set Y2 [expr {0.5 * $yMin}]”中调用的“expr {0.5 * $yMin}”时,不能使用空字符串作为“*”的操作数

即使只打印了yMin,它仍然有空操作数错误。

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

表达式“”中的空表达式(解析表达式“”)
从“expr $yMin”
中调用 从“set Y1 [expr $yMin]”中调用

但是有一个有趣的测试。如果添加花括号,它会起作用!

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

实际上,这似乎无法重现问题(这就是我有这篇文章的原因)。但它至少可以是一个模板。


试错

以下代码用于检查它是否真的为空。原来不是空的。

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

yMin 不为空:<-6.149999999999999e-02>

最后,我尝试了trimmapregsub来删除任何空格和制表符,但它们都不起作用。

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 不为空:<-6.149999999999999e-02>

这里我只显示regsub的结果。其他人的结果是一样的。

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

在执行从“set reg_Y2 [expr {0.5 * $reg_yMin}]”中调用的
“expr {0.5 * $reg_yMin}”时,不能使用空字符串作为“*”的操作数

请你帮助我好吗?我真的不知道我还能尝试什么。提前致谢。


更新和回复

埃尔贡

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

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

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


在执行
从“set Y2 [expr {0.5 * $yMin}]”中调用的“expr {0.5 * $yMin}”时,不能使用空字符串作为“*”的操作数

贝纳哈

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

value 是一个引用计数为 4 的字符串,对象指针位于 0x44ed0910,内部表示 0x450d6120:(nil),字符串表示“-6.14999999999 ....”

肖恩

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 是一个引用计数为 4 的字符串,对象指针位于 0x44ed6030,内部表示为 0x450de4b0:(nil),字符串表示“-6.1499999999 ...”

2d362e313439393939393939393939393939652d3032

value 是一个字节数组,引用计数为 3,内部表示为 3,对象指针位于 04460 0x44ee0dc0:(nil),字符串表示“-6.1499999999...”

1

值是引用计数为 4 的 double,对象指针位于 0x44ed6030,内部表示 0xbfaf7ced916872af:(nil),字符串表示“-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
新_Y2:-0.030749999999999996

谢尔特布朗来说,

错误信息已更改!也许它表明了什么?

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

value 是一个引用计数为 4 的字符串,对象指针位于 0x44ec28a0,内部表示 0x450be540:(nil),字符串表示“-6.1499999999...”

value 是一个引用计数为 2 的字符串,对象指针位于 0x446bbc70,内部表示 0x44695fd0 :(nil),字符串表示“-6.149999999...”

不能使用非数字字符串作为“*”的操作数,
同时执行

“set Y2 [expr {0.5 * $yMin}]"

如果在 string 为 double -strict $yMin 后值变为 double 后计算仍然失败,则取二进制编码十六进制 $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

yMin 是双倍的吗?:1
yMin:-6.149999999999999e-02
double yMin 的二进制:2d362e313439393939393939393939393939652d3032
双二进制双精度:-6.149999999999999e-02
不能使用空字符串作为“*”
在执行“expr {} 0 * $double_”
中的操作数 {} “设置 Y2 [expr {0.5 * $double_binary_yMin}]”

你用 tcl::mathop::* 0.5 $yMin 得到什么?

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


在执行从“puts [tcl::mathop::* 0.5 $yMin]”中调用的
“tcl::mathop::* 0.5 $yMin”时,不能使用空字符串作为“*”的操作数


相关帖子

  1. 为什么 Tcler 建议支持你的expressions?
  2. 这是什么意思-不能在tcl-上使用空字符串作为“*”的操作数?如何解决
  3. 如何在 TCL 中去除字符串中的空格?
  4. 使用 TCL 从文件中读取字符串后从字符串中删除空格
  5. tcl 脚本中@处缺少操作数
  6. 确定 Tcl 中变量的类型
4

3 回答 3

3

如果没有该变量的确切起点bbox,我们只能真正推测。该值应该起作用:

% set yMin -6.149999999999999e-02
-6.149999999999999e-02
% expr {0.5 * $yMin}
-0.030749999999999996

expr如果输入数据是纯旧的虚假数据,并且空字符串的数字永远不足以支持乘法,那么所有可能失败的方法都将无济于事。(这不是 Python!)我们必须备份几个步骤。

怀疑问题在于bbox变量有时不是您期望的形状,有时具有这样的值:1.0 -6.149999999999999e-02 3.0 4.0. 在这种情况下,[lindex [lindex $bbox 0] 1]将产生一个空字符串(因为从列表的末尾开始索引是因为语言的历史):

% set bbox {1.0 -6.149999999999999e-02 3.0 4.0}
1.0 -6.149999999999999e-02 3.0 4.0
% puts >[lindex [lindex $bbox 0] 1]<
><

在这种情况下,仅使用lindex $bbox 1会更好。

% puts >[lindex $bbox 1]<
>-6.149999999999999e-02<

嵌套有一个简写lindex

lindex $boox 0 1

但是边界框(至少当它们来自 Tk 时)通常只是四个数值的简单列表,因此在它们上使用嵌套形式很可能既错误又低效。X1 Y1 X2 Y2

于 2021-09-16T11:09:26.613 回答
2

这只是猜测:您指出坐标来自某个晦涩的来源。也许开发人员创建了一个新的对象类型,但没有正确实现转换过程。当您打印该值时,将使用字符串表示。但是当你尝试乘以它想要将神秘对象类型转换为双精度的值时,这似乎无法正常工作。

您一直在尝试删除空白。但是因为没有空格,所以值没有被修改。但是如果你要添加空白会发生什么?例如:set yMin " $yMin"。这应该将变量转换为纯字符串(您可以检查tcl::unsupported::representation)。如果您随后尝试将其相乘,则将使用将字符串转换为双精度的常规 Tcl 转换过程。请注意,数字周围的空格对于 是完全可以接受的expr,因此您应该能够将修改后的 $yMin 相乘。

于 2021-09-16T18:56:08.123 回答
1

这不是答案,而是带有格式的评论

% 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

您的代码中发生的其他事情正在改变变量的值。看看如何创建一个最小的、可重现的示例

于 2021-09-16T10:33:38.303 回答