5

Using writef(), I can control the output precision of a floating-point number, for example:

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

but if I use writeln() for convenience, the number is output with 6 digits:

writeln( 1.0 / 3.0 );                   // 0.333333

Is there possibly a way to control the default output precision of floating-point numbers for writeln()..? (e.g., via some environment variable?)

For comparison, some languages output 15 digits and some 6 digits by default, so the result seems to vary depending on languages (or compilers).

# 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
roygvib
  • 7,218
  • 2
  • 19
  • 36

2 Answers2

5

Use 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

You can also pass other things to new iostyle(), for example:

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
Vass
  • 431
  • 2
  • 4
5

Yes there is. In Chapel, I/O is performed on channels. Each channel has an I/O style (represented by a record of type iostyle) which specifies how values are printed to that channel if a more specific style is not provided within the read/write call itself. A call to writeln() is essentially a call to stdout.writeln() where stdout is a channel whose output shows up in the console.

The following example shows how to change the I/O style of stdout (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._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 );

where the output is:

0.333333
0.333333333333333
0.333333

Note that it isn't safe to change the style of a channel in parallel code without locking it first. Since the example above is completely serial, it's OK, but in the context of a larger, potentially parallel, program, the better approach would be to lock the channel before setting its style, as follows (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's online documentation has more information about I/O styles, the fields of the iostyle record, and locking of channels.

Brad
  • 3,839
  • 7
  • 25
  • 2
    Thanks very much for more examples! And I have one question... For a small test code (with a single file), is it usually okay to just put "stdout._set_style(new iostyle(precision=10));" at the top of that source file, even if it performs "forall" later in the code, without stdout.lock/unlock? (I.e., I will not change such IO style during the parallel execution.) – roygvib Jan 23 '19 at 18:55
  • 3
    I believe that should be safe. Unless I'm mistaken, the locking should only be necessary if the style is changed while other tasks are using the channel simultaneously. – Brad Jan 23 '19 at 18:58