1 #!/usr/local/bin/perl
\r
2 # ********************************************************************
\r
4 # * Copyright (c) 2006, International Business Machines Corporation and
\r
5 # * others. All Rights Reserved.
\r
6 # ********************************************************************
\r
8 my $PLUS_MINUS = "±";
\r
10 #|#---------------------------------------------------------------------
\r
11 #|# Format a confidence interval, as given by a Dataset. Output is as
\r
13 #|# 241.23 - 241.98 => 241.5 +/- 0.3
\r
14 #|# 241.2 - 243.8 => 242 +/- 1
\r
15 #|# 211.0 - 241.0 => 226 +/- 15 or? 230 +/- 20
\r
16 #|# 220.3 - 234.3 => 227 +/- 7
\r
17 #|# 220.3 - 300.3 => 260 +/- 40
\r
18 #|# 220.3 - 1000 => 610 +/- 390 or? 600 +/- 400
\r
19 #|# 0.022 - 0.024 => 0.023 +/- 0.001
\r
20 #|# 0.022 - 0.032 => 0.027 +/- 0.005
\r
21 #|# 0.022 - 1.000 => 0.5 +/- 0.5
\r
22 #|# In other words, take one significant digit of the error value and
\r
23 #|# display the mean to the same precision.
\r
24 #|sub formatDataset {
\r
26 #| my $lower = $ds->getMean() - $ds->getError();
\r
27 #| my $upper = $ds->getMean() + $ds->getError();
\r
29 #| # Find how many initial digits are the same
\r
30 #| while ($lower < 1 ||
\r
31 #| int($lower) == int($upper)) {
\r
36 #| while ($lower >= 10 &&
\r
37 #| int($lower) == int($upper)) {
\r
44 #---------------------------------------------------------------------
\r
45 # Format a number, optionally with a +/- delta, to n significant
\r
48 # @param significant digit, a value >= 1
\r
50 # @param time in seconds to be formatted
\r
51 # @optional delta in seconds
\r
53 # @return string of the form "23" or "23 +/- 10".
\r
59 my $delta = shift; # may be undef
\r
61 my $result = formatSigDig($sigdig, $a*$mult);
\r
62 if (defined($delta)) {
\r
63 my $d = formatSigDig($sigdig, $delta*$mult);
\r
64 # restrict PRECISION of delta to that of main number
\r
65 if ($result =~ /\.(\d+)/) {
\r
66 # TODO make this work for values with all significant
\r
67 # digits to the left of the decimal, e.g., 1234000.
\r
69 # TODO the other thing wrong with this is that it
\r
70 # isn't rounding the $delta properly. Have to put
\r
71 # this logic into formatSigDig().
\r
73 $d =~ s/\.(\d{$x})\d+/.$1/;
\r
75 $result .= " $PLUS_MINUS " . $d;
\r
80 #---------------------------------------------------------------------
\r
81 # Format a time, optionally with a +/- delta, to n significant
\r
84 # @param significant digit, a value >= 1
\r
85 # @param time in seconds to be formatted
\r
86 # @optional delta in seconds
\r
88 # @return string of the form "23 ms" or "23 +/- 10 ms".
\r
93 my $delta = shift; # may be undef
\r
95 my @MULT = (1 , 1e3, 1e6, 1e9);
\r
96 my @SUFF = ('s' , 'ms', 'us', 'ns');
\r
98 # Determine our scale
\r
100 #always do seconds if the following line is commented out
\r
101 ++$i while ($a*$MULT[$i] < 1 && $i < @MULT);
\r
103 formatNumber($sigdig, $MULT[$i], $a, $delta) . ' ' . $SUFF[$i];
\r
106 #---------------------------------------------------------------------
\r
107 # Format a percentage, optionally with a +/- delta, to n significant
\r
110 # @param significant digit, a value >= 1
\r
111 # @param value to be formatted, as a fraction, e.g. 0.5 for 50%
\r
112 # @optional delta, as a fraction
\r
114 # @return string of the form "23 %" or "23 +/- 10 %".
\r
116 sub formatPercent {
\r
117 my $sigdig = shift;
\r
119 my $delta = shift; # may be undef
\r
121 formatNumber($sigdig, 100, $a, $delta) . '%';
\r
124 #---------------------------------------------------------------------
\r
125 # Format a number to n significant digits without using exponential
\r
128 # @param significant digit, a value >= 1
\r
129 # @param number to be formatted
\r
131 # @return string of the form "1234" "12.34" or "0.001234". If
\r
132 # number was negative, prefixed by '-'.
\r
135 my $n = shift() - 1;
\r
138 local $_ = sprintf("%.${n}e", $a);
\r
139 my $sign = (s/^-//) ? '-' : '';
\r
143 if (/^(\d)\.(\d+)e([-+]\d+)$/) {
\r
144 my ($d, $dn, $e) = ($1, $2, $3);
\r
148 $d .= '0' while ($e > length($d));
\r
153 if ($e == length($d)) {
\r
154 $result = $sign . $d;
\r
156 $result = $sign . substr($d, 0, $e) . '.' . substr($d, $e);
\r
159 die "Can't parse $_";
\r