% expr 60.9-59.7
1.1999999999999957
似乎在上面的示例中expr
以更高的精度输出浮点运算的结果。
对于 这个简单的东西,我希望有一个更合理的输出,比如这个C ++代码的输出:
#include <iostream>
int main()
{
double a = 60.9;
a -= 59.7;
std::cout << "double a = " << a << std::endl;
float b = 60.9;
b -= 59.7;
std::cout << "float b = " << b << std::endl;
}
输出:
double a = 1.2
float b = 1.2
因此问题:
为什么TCL输出expr
结果的精度高于计算它们的精度,从而导致lsb伪影?
是否可以通过设置类似全局精度变量或全局输出分辨率变量之类的东西来阻止这种歪曲呢?
答案 0 :(得分:2)
有一个全局变量可以控制Tcl在转换为字符串时使用的精度位数:tcl_precision。但是,在查找这个答案时,我发现自从上次使用它以来它已被弃用,并且使用format命令的显示控制是首选。有关如何使用它以及为什么不应该使用它的详细信息,请参阅http://wiki.tcl.tk/1650。
请注意,您将遇到与C ++相同的问题;这是浮点数的IEEE格式问题,而不是Tcl。 &#34;多余&#34;您所抱怨的精确度仅仅是显示输出的确切值而不对其进行格式化以满足您的需求的效果。 C / C ++&amp; Tcl是格式化C输出的默认精度是6位数。
答案 1 :(得分:0)
This answer表示,对于C ++,这个问题也出现了。
您无法控制结果的值。您想控制输出方式:
% expr 60.9-59.7
1.1999999999999957
% puts [format {%.2f} [expr {60.9-59.7}]]
1.20
答案 2 :(得分:0)
浮点运算由Tcl的运行时执行,它是从C编译的。它与从C / C ++编译的任何其他可执行文件中的浮点运算完全相同。但是,在Tcl中,与C / C ++不同,字符串表示可能用于进一步的计算*,这意味着任意精度损失将是一件坏事。
你可以用一个基本上看起来像这样的命令替换普通的puts
命令(只是一个概念验证:实际上你需要更多的基础设施来1)处理额外的参数,到2 )避免它在puts
中以不同的方式工作 - 捕获shell,以及3)将对此的一些控制权返回给程序员,但它非常可行):
proc _puts str {
if {[string is double -strict $str]} {
puts [format %g $str]
} else {
puts $str
}
}
默认情况下会打印圆角浮点数。
*)几十年前,Tcl代码经过字节编译,使用与其字符串表示一起存储的实际浮点值,但编译器仍然向程序员的意愿鞠躬,如果他们决定使用SR由于某些原因。信任s.r.的能力成为&#34;无损&#34;是语言和程序员之间合同的一部分,不太可能改变。