Точность вывода `writeln ()` для чисел с плавающей точкой - PullRequest
0 голосов
/ 23 января 2019

Используя 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

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Да, есть.В часовне ввод / вывод выполняется на каналах .Каждый канал имеет стиль ввода / вывода (представленный записью типа iostyle), который определяет, как значения печатаются в этот канал, если в самом вызове чтения / записи не предусмотрен более конкретный стиль.Вызов writeln() по сути является вызовом stdout.writeln(), где stdout - это канал, выход которого отображается в консоли.

В следующем примере показано, как изменить стиль ввода-вывода stdout ( Попробуйте онлайн ):

// 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

Обратите внимание, что нельзя параллельно менять стиль канала параллельнокод без блокировки в первую очередь.Поскольку приведенный выше пример является полностью последовательным, все в порядке, но в контексте более крупной, потенциально параллельной программы лучшим подходом будет блокировка канала перед установкой его стиля следующим образом ( Попробуйте в Интернете ):

// 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 содержит больше информации о стилях ввода-вывода , полях iostyle записи и блокировкеканалы . * * тысяча двадцать-девять

0 голосов
/ 23 января 2019

Используйте iostyle и _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
...