]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | #!/usr/local/bin/perl |
2 | # ******************************************************************** | |
f3c0d7a5 A |
3 | # * Copyright (C) 2016 and later: Unicode, Inc. and others. |
4 | # * License & terms of use: http://www.unicode.org/copyright.html#License | |
5 | # ******************************************************************** | |
6 | # ******************************************************************** | |
b75a7d8f A |
7 | # * COPYRIGHT: |
8 | # * Copyright (c) 2002, International Business Machines Corporation and | |
9 | # * others. All Rights Reserved. | |
10 | # ******************************************************************** | |
11 | ||
12 | my $PLUS_MINUS = "±"; | |
13 | ||
14 | #|#--------------------------------------------------------------------- | |
15 | #|# Format a confidence interval, as given by a Dataset. Output is as | |
16 | #|# as follows: | |
17 | #|# 241.23 - 241.98 => 241.5 +/- 0.3 | |
18 | #|# 241.2 - 243.8 => 242 +/- 1 | |
19 | #|# 211.0 - 241.0 => 226 +/- 15 or? 230 +/- 20 | |
20 | #|# 220.3 - 234.3 => 227 +/- 7 | |
21 | #|# 220.3 - 300.3 => 260 +/- 40 | |
22 | #|# 220.3 - 1000 => 610 +/- 390 or? 600 +/- 400 | |
23 | #|# 0.022 - 0.024 => 0.023 +/- 0.001 | |
24 | #|# 0.022 - 0.032 => 0.027 +/- 0.005 | |
25 | #|# 0.022 - 1.000 => 0.5 +/- 0.5 | |
26 | #|# In other words, take one significant digit of the error value and | |
27 | #|# display the mean to the same precision. | |
28 | #|sub formatDataset { | |
29 | #| my $ds = shift; | |
30 | #| my $lower = $ds->getMean() - $ds->getError(); | |
31 | #| my $upper = $ds->getMean() + $ds->getError(); | |
32 | #| my $scale = 0; | |
33 | #| # Find how many initial digits are the same | |
34 | #| while ($lower < 1 || | |
35 | #| int($lower) == int($upper)) { | |
36 | #| $lower *= 10; | |
37 | #| $upper *= 10; | |
38 | #| $scale++; | |
39 | #| } | |
40 | #| while ($lower >= 10 && | |
41 | #| int($lower) == int($upper)) { | |
42 | #| $lower /= 10; | |
43 | #| $upper /= 10; | |
44 | #| $scale--; | |
45 | #| } | |
46 | #|} | |
47 | ||
48 | #--------------------------------------------------------------------- | |
49 | # Format a number, optionally with a +/- delta, to n significant | |
50 | # digits. | |
51 | # | |
52 | # @param significant digit, a value >= 1 | |
53 | # @param multiplier | |
54 | # @param time in seconds to be formatted | |
55 | # @optional delta in seconds | |
56 | # | |
57 | # @return string of the form "23" or "23 +/- 10". | |
58 | # | |
59 | sub formatNumber { | |
60 | my $sigdig = shift; | |
61 | my $mult = shift; | |
62 | my $a = shift; | |
63 | my $delta = shift; # may be undef | |
64 | ||
65 | my $result = formatSigDig($sigdig, $a*$mult); | |
66 | if (defined($delta)) { | |
67 | my $d = formatSigDig($sigdig, $delta*$mult); | |
68 | # restrict PRECISION of delta to that of main number | |
69 | if ($result =~ /\.(\d+)/) { | |
70 | # TODO make this work for values with all significant | |
71 | # digits to the left of the decimal, e.g., 1234000. | |
72 | ||
73 | # TODO the other thing wrong with this is that it | |
74 | # isn't rounding the $delta properly. Have to put | |
75 | # this logic into formatSigDig(). | |
76 | my $x = length($1); | |
77 | $d =~ s/\.(\d{$x})\d+/.$1/; | |
78 | } | |
79 | $result .= " $PLUS_MINUS " . $d; | |
80 | } | |
81 | $result; | |
82 | } | |
83 | ||
84 | #--------------------------------------------------------------------- | |
85 | # Format a time, optionally with a +/- delta, to n significant | |
86 | # digits. | |
87 | # | |
88 | # @param significant digit, a value >= 1 | |
89 | # @param time in seconds to be formatted | |
90 | # @optional delta in seconds | |
91 | # | |
92 | # @return string of the form "23 ms" or "23 +/- 10 ms". | |
93 | # | |
94 | sub formatSeconds { | |
95 | my $sigdig = shift; | |
96 | my $a = shift; | |
97 | my $delta = shift; # may be undef | |
98 | ||
99 | my @MULT = (1 , 1e3, 1e6, 1e9); | |
100 | my @SUFF = ('s' , 'ms', 'us', 'ns'); | |
101 | ||
102 | # Determine our scale | |
103 | my $i = 0; | |
104 | #always do seconds if the following line is commented out | |
105 | ++$i while ($a*$MULT[$i] < 1 && $i < @MULT); | |
106 | ||
107 | formatNumber($sigdig, $MULT[$i], $a, $delta) . ' ' . $SUFF[$i]; | |
108 | } | |
109 | ||
110 | #--------------------------------------------------------------------- | |
111 | # Format a percentage, optionally with a +/- delta, to n significant | |
112 | # digits. | |
113 | # | |
114 | # @param significant digit, a value >= 1 | |
115 | # @param value to be formatted, as a fraction, e.g. 0.5 for 50% | |
116 | # @optional delta, as a fraction | |
117 | # | |
118 | # @return string of the form "23 %" or "23 +/- 10 %". | |
119 | # | |
120 | sub formatPercent { | |
121 | my $sigdig = shift; | |
122 | my $a = shift; | |
123 | my $delta = shift; # may be undef | |
124 | ||
125 | formatNumber($sigdig, 100, $a, $delta) . '%'; | |
126 | } | |
127 | ||
128 | #--------------------------------------------------------------------- | |
129 | # Format a number to n significant digits without using exponential | |
130 | # notation. | |
131 | # | |
132 | # @param significant digit, a value >= 1 | |
133 | # @param number to be formatted | |
134 | # | |
135 | # @return string of the form "1234" "12.34" or "0.001234". If | |
136 | # number was negative, prefixed by '-'. | |
137 | # | |
138 | sub formatSigDig { | |
139 | my $n = shift() - 1; | |
140 | my $a = shift; | |
141 | ||
142 | local $_ = sprintf("%.${n}e", $a); | |
143 | my $sign = (s/^-//) ? '-' : ''; | |
144 | ||
145 | my $a_e; | |
146 | my $result; | |
147 | if (/^(\d)\.(\d+)e([-+]\d+)$/) { | |
148 | my ($d, $dn, $e) = ($1, $2, $3); | |
149 | $a_e = $e; | |
150 | $d .= $dn; | |
151 | $e++; | |
152 | $d .= '0' while ($e > length($d)); | |
153 | while ($e < 1) { | |
154 | $e++; | |
155 | $d = '0' . $d; | |
156 | } | |
157 | if ($e == length($d)) { | |
158 | $result = $sign . $d; | |
159 | } else { | |
160 | $result = $sign . substr($d, 0, $e) . '.' . substr($d, $e); | |
161 | } | |
162 | } else { | |
163 | die "Can't parse $_"; | |
164 | } | |
165 | $result; | |
166 | } | |
167 | ||
168 | 1; | |
169 | ||
170 | #eof |