Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

chapel

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
like image 647
roygvib Avatar asked Jan 23 '19 16:01

roygvib


People also ask

How do you find the precision of a floating-point?

The precision of floating-point numbers is either single or double, based on the number of hexadecimal digits in the fraction. A small integer is a binary integer with a precision of 15 bits. The range of small integers is -32768 to +32767. A large integer is a binary integer with a precision of 31 bits.

What does precision mean in floating-point numbers?

Precision: The smallest change that can be represented in floating point representation is called as precision. The fractional part of a single precision normalized number has exactly 23 bits of resolution, (24 bits with the implied bit).

What is the precision of float data type?

FLOAT data types usually require 8 bytes of storage per value. Conversion of a FLOAT value to a DECIMAL value results in 17 digits of precision.

How many precision does a float have?

The data type float has 24 bits of precision. This is equivalent to only about 7 decimal places. (The rest of the 32 bits are used for the sign and size of the number.) The number of places of precision for float is the same no matter what the size of the number.


2 Answers

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
like image 182
Vass Avatar answered Oct 06 '22 16:10

Vass


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.

like image 30
Brad Avatar answered Oct 06 '22 18:10

Brad