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