浮点数的 `writeln()` 输出精度

Output precision of `writeln()` for floating-point numbers

利用writef(),我可以控制一个浮点数的输出精度,例如:

writef( "%20.15dr\n", 1.0 / 3.0 );      // 0.333333333333333

但如果我为了方便使用writeln(),则数字输出为6位:

writeln( 1.0 / 3.0 );                   // 0.333333

有没有办法控制 writeln().. 浮点数的默认输出精度? (例如,通过一些环境变量?)

为了比较,一些语言默认输出15位和一些6位,所以结果似乎因语言(或编译器)而异。

# python2
print 1.0 / 3.0      # 0.333333333333
# python3
print( 1.0 / 3.0 )   # 0.3333333333333333
# julia
println( 1.0 / 3.0 )   # 0.3333333333333333
# gfortran
print *, 1.0d0 / 3.0d0   # 0.33333333333333331
# swift
print( 1.0 / 3.0 )       # 0.333333333333333
# nim
echo( 1.0 / 3.0 )       # 0.3333333333333333
# g++
cout << 1.0 / 3.0 << endl;   # 0.333333
# d (dmd)
writeln( 1.0 / 3.0 );      # 0.333333

使用iostyle and _set_style()

writeln(100.0/3.0);   // 33.3333

stdout.lock();
stdout._set_style(new iostyle(precision=10));
stdout.unlock();

writeln(100.0/3.0);   // 33.33333333

你也可以传递其他东西给new iostyle(),例如:

precision=10, realfmt=0          // like %.10g in C:  33.33333333      (default)
precision=10, realfmt=1          // like %.10f in C:  33.3333333333
precision=10, realfmt=2          // like %.10e in C:  3.3333333333e+01

是的。在 Chapel 中,I/O 在 频道 上执行。每个通道都有一个 I/O 样式(由 iostyle 类型的记录表示),它指定如果 read/write 调用本身未提供更具体的样式,则如何将值打印到该通道。对 writeln() 的调用本质上是对 stdout.writeln() 的调用,其中 stdout 是一个通道,其输出显示在控制台中。

以下示例显示如何更改标准输出 (Try it Online) 的 I/O 样式:

// print to stdout using its default style                                                
writeln( 1.0 / 3.0 );

// create a new IO style with a precision of 15                                   
var style = new iostyle(precision=15);

// change stdout to use this new style                                          
stdout._set_style(style);

// print using the new style                                                    
writeln( 1.0 / 3.0 );

// restore the default style and print once more                                
stdout._set_style(defaultIOStyle());
writeln( 1.0 / 3.0 );

其中输出为:

0.333333
0.333333333333333
0.333333

请注意,在并行代码中更改通道的样式而不先锁定它是不安全的。由于上面的示例是完全串行的,所以没关系,但是在更大的、可能并行的程序的上下文中,更好的方法是在设置其样式之前锁定通道,如下所示 (Try it Online):

// print to stdout using its default style                                                
writeln( 1.0 / 3.0 );

// create a new IO style with a precision of 15                                   
var style = new iostyle(precision=15);

// change stdout to use this new style                                          
stdout.lock();
stdout._set_style(style);
stdout.unlock();

// print using the new style                                                    
writeln( 1.0 / 3.0 );

// restore the default style and print once more                                
stdout.lock();
stdout._set_style(defaultIOStyle());
stdout.unlock();
writeln( 1.0 / 3.0 );

Chapel 的联机文档包含有关 I/O styles, the fields of the iostyle record, and locking of channels 的更多信息。