如何使用 Perl 格式写出科学记数法?

发布于 2024-09-19 00:19:56 字数 278 浏览 0 评论 0原文

我一直使用 printf,从未使用过 write/format。有没有办法使用某种格式重现 printf("%12.5e", $num) ?我无法消化 perlform 文档,但我没有看到一种简单的方法做这个。

编辑:根据我得到的答案,我将继续使用 printf 。

I've always used printf, and I've never used write/format. Is there any way to reproduce printf("%12.5e", $num) using a format? I'm having trouble digesting the perlform documentation, but I don't see a straightforward way of doing this.

EDIT: based on the answers I got, I'm just gonna keep on using printf.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拧巴小姐 2024-09-26 00:19:56

简短的回答,不要使用格式。

未经研究的答案,当然,只需使用 sprintf

#!/usr/bin/perl

use strict;
use warnings;

our $num = .005;

write;

format STDOUT =
@>>>>>>>>>>>>>>>>>
sprintf("%12.5e", $num)
.

说真的,如果您需要 Perl 5 格式之类的东西,请查看 Perl6::Form (注意,这是一个 Perl 5 模块,它只是实现了建议的 Perl 6 版本格式)。

Short answer, don't use formats.

Unresearched answer, sure, just use sprintf:

#!/usr/bin/perl

use strict;
use warnings;

our $num = .005;

write;

format STDOUT =
@>>>>>>>>>>>>>>>>>
sprintf("%12.5e", $num)
.

Seriously, if you need something like Perl 5 formats, take a look at Perl6::Form (note, this is a Perl 5 module, it just implements the proposed Perl 6 version of formats).

┾廆蒐ゝ 2024-09-26 00:19:56

我完全同意查斯的观点。欧文斯谈一般格式。 Format 在 15 年前确实很出色,但是 format 并没有跟上 Perl 其余部分的进步。

这是我经常使用的面向行输出的技术。您可以使用 formline 这是 format 使用的公共内部函数之一Format 是面向页面的。很难执行诸如跨列或根据数据逐行更改格式之类的操作。您可以使用 format 使用的相同文本格式化逻辑来格式化单行,然后自己输出该结果。

一个(混乱的)示例:

use strict; use warnings;

sub print_line {
    my $pic=shift;
    my @args=@_;

    formline($pic,@args);
    print "$^A\n";
    $^A='';
}

my ($wlabel, $wlow, $whigh, $wavg)=(0,0,0,0);
my ($plabel,$plow,$phigh, $pavg);
my ($s_low,$s_high,$s_avg)=qw(%.2f %.2e %.2f);


my @results=( ["Label 1", 3.445, 0.00006678, .025],
           ["Label 2", 12.5555556, 55.112, 1.11],
           ["Wide Label 3", 1231.11, 1555.0, 66.66] );

foreach (@results) { 
    my $tmp;
    $tmp=length($_->[0]);
    $wlabel=$tmp if $tmp>$wlabel; 

    $tmp=length(sprintf($s_low,$_->[3]));
    $wlow=$tmp if $tmp>$wlow;

    $tmp=length(sprintf($s_high,$_->[2]));
    $whigh=$tmp if $tmp>$whigh;

    $tmp=length(sprintf($s_avg,$_->[1]));
    $wavg=$tmp if $tmp>$wavg;
}

print "\n\n";
my @a1=("Label", "Rate - Operations / sec");
my @a2=("Text", "Average", "High", "Low");
my @a3=("----------", "-------", "----", "---");
my $l1fmt="@".'|' x $wlabel."   @".'|'x($whigh+$wavg+$wlow+6);

my $l2fmt="@".'|' x $wlabel."    @".'|' x $wavg."   @".'|' x $whigh . 
           "   @".'|' x $wlow;
print_line($l1fmt,@a1);
print_line($l2fmt,@a2);
print_line($l2fmt,@a3);

$plabel="@".'>' x $wlabel;
$phigh="@".'>' x $whigh;
$pavg="@".'>' x $wavg;
$plow="@".'<' x $wlow;


foreach (@results) {
    my $pic="$plabel   $pavg   $phigh   $plow";
    my $mark=$_->[0];
    my $avg=sprintf($s_avg,$_->[1]);
    my $high=sprintf($s_high,$_->[2]);
    my $low=sprintf($s_low,$_->[3]);
    print_line($pic,$mark,$avg,$high,$low);
}
print "\n\n";

输出如下:

    Label         Rate - Operations / sec
    Text         Average      High       Low
 ----------      -------      ----       ---
      Label 1       3.44    6.68e-05   0.03
      Label 2      12.56    5.51e+01   1.11
 Wide Label 3    1231.11    1.56e+03   66.66

请注意,列的宽度是根据 sprintf 格式字符串格式化的数据宽度设置的。然后您可以向左、居中、向右证明该结果。 “低”数据列左对齐,其余数据右对齐。您可以通过标量 $plow 中使用的符号来更改它,它与 format 语法相同。顶部的标签居中,“速率 - 操作/秒”标签跨越 3 列。

这显然不是“生产就绪”的代码,但我想你已经明白了。您需要根据所需宽度进一步检查列的总宽度等。您必须手动完成格式为您所做的一些工作,但使用这种方法可以更加灵活。例如,使用 sprintf 可以很容易地在一行的多个部分中使用此方法。

干杯。

I totally agree with Chas. Owens on formats in general. Format was really slick 15 years ago, but format has not kept up with the advancements of the rest of Perl.

Here is a technique for line oriented output that I use time to time. You can use formline which is one of the public internal functions used by format. Format is page oriented. It is very hard to do things like span columns or change the format by line depending on the data. You can format a single line using the same text formatting logic used by format and then output that result yourself.

A (messy) example:

use strict; use warnings;

sub print_line {
    my $pic=shift;
    my @args=@_;

    formline($pic,@args);
    print "$^A\n";
    $^A='';
}

my ($wlabel, $wlow, $whigh, $wavg)=(0,0,0,0);
my ($plabel,$plow,$phigh, $pavg);
my ($s_low,$s_high,$s_avg)=qw(%.2f %.2e %.2f);


my @results=( ["Label 1", 3.445, 0.00006678, .025],
           ["Label 2", 12.5555556, 55.112, 1.11],
           ["Wide Label 3", 1231.11, 1555.0, 66.66] );

foreach (@results) { 
    my $tmp;
    $tmp=length($_->[0]);
    $wlabel=$tmp if $tmp>$wlabel; 

    $tmp=length(sprintf($s_low,$_->[3]));
    $wlow=$tmp if $tmp>$wlow;

    $tmp=length(sprintf($s_high,$_->[2]));
    $whigh=$tmp if $tmp>$whigh;

    $tmp=length(sprintf($s_avg,$_->[1]));
    $wavg=$tmp if $tmp>$wavg;
}

print "\n\n";
my @a1=("Label", "Rate - Operations / sec");
my @a2=("Text", "Average", "High", "Low");
my @a3=("----------", "-------", "----", "---");
my $l1fmt="@".'|' x $wlabel."   @".'|'x($whigh+$wavg+$wlow+6);

my $l2fmt="@".'|' x $wlabel."    @".'|' x $wavg."   @".'|' x $whigh . 
           "   @".'|' x $wlow;
print_line($l1fmt,@a1);
print_line($l2fmt,@a2);
print_line($l2fmt,@a3);

$plabel="@".'>' x $wlabel;
$phigh="@".'>' x $whigh;
$pavg="@".'>' x $wavg;
$plow="@".'<' x $wlow;


foreach (@results) {
    my $pic="$plabel   $pavg   $phigh   $plow";
    my $mark=$_->[0];
    my $avg=sprintf($s_avg,$_->[1]);
    my $high=sprintf($s_high,$_->[2]);
    my $low=sprintf($s_low,$_->[3]);
    print_line($pic,$mark,$avg,$high,$low);
}
print "\n\n";

Outputs this:

    Label         Rate - Operations / sec
    Text         Average      High       Low
 ----------      -------      ----       ---
      Label 1       3.44    6.68e-05   0.03
      Label 2      12.56    5.51e+01   1.11
 Wide Label 3    1231.11    1.56e+03   66.66

Notice that the width of the columns is set based on the width of the data as formatted by the sprintf format string. You can then left, center, right justify that result. The "Low" data column is left justified, the rest of the data are right justified. You can change this by the symbol used in the scalar $plow and it is the same as format syntax. The labels at the top are centered and the "Rate - Operations / sec" label spans 3 columns.

This is obviously not "production ready" code, but you get the drift I think. You would need to further check the total width of the columns against desired width, etc. You have to manually do some of the work that format does for you, but you have far more flexibility with this approach. It is very easy to use this method for several sections of a line with sprintf for example.

Cheers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文