Formatted value-error string

Average rating
(0 votes)

The function ValueErrorString(value, error, [delta, format, expformat, nonmetric]) returns a formatted value-error string terminating with a metric prefix. The intended use is with "dimensioned" quantities, see the examples.

Examples:

print ValueErrorString(12.34e-5, 1.11e-5) + "V"
  0.12(1) mV
•print ValueErrorString(12.34e-5, 1.11e-5, delta=1e-6, format="v(±e)") + "F"
  123(±11)µF
•print ValueErrorString(12.34e-5, 1.11e-5, delta=1e-7, format="(v ± e) ") + "T"
  (123.4 ± 11.1) µT

The optional parameters make this function quite versatile. They are explained in detail in the code.

W. Harneit

// function/S ValueErrorString(value, error, [delta, format, expformat, nonmetric]) 
//	returns a formatted value-error string terminating with a metric prefix
//	intended use is with properly "dimensioned" quantities, see examples
//
// 	Examples:
// 	•print ValueErrorString(12.34e-5, 1.11e-5) + "V"
//	  0.12(1) mV
// 	•print ValueErrorString(12.34e-5, 1.11e-5, delta=1e-6, format="v(±e)") + "F"
//	  123(±11)µF
// 	•print ValueErrorString(12.34e-5, 1.11e-5, delta=1e-7, format="(v ± e) ") + "T"
//	  (123.4 ± 11.1) µT
//
//	Required parameters:	
//	variable value, error
//
//	Optional parameters:
//	variable delta (default: delta = error) -- the smallest distinguishable increment
//		this influences how many significant digits will be returned in the output (see examples)
//	string format (default: "v(e) ") -- format of value and error
//		"v" and "e" (must be small letters) are placeholders for value and error
//		if "v" is missing, output will start with value, followed by the rest of whatever you pass for format
//		if "e" is missing, "(±e) " will be appended next, then the exponential prefix (see below)
//			thus, if you say  format = " ", you'll get the format "v (±e) "
//		spaces and brackets are allowed and will appear in the output as expected
//	string expformat (default: "x 10\S%d\M ") -- format of exponential prefix if not metric
//		normally, a metric prefix is appended as appropriate (e.g., "µ" for 10^(-6))
//		the prefix is chosen such that no trailing zeroes occur in most cases (see examples)
//		if the value is outside of the range of WM prefixes "TGMk.mµnpf", the prefix is a number.
//			the default "x 10\S%d\M " is useful for Annotations etc. with formatted text
//			the prefix value is then floor(log(abs(value))) (i.e., 20 for value=3.45e20)
//		if you override the default, use %d or %+d as a placeholder for the exponent
//			"E%d" will give E20 or E-20 if the exponent is +20 or -20.
//			"E%+d" will give E+20 or E-20 if the exponent is +20 or -20.
//	variable nonmetric (default = 0) -- set to non-zero value to suppress metric prefixes
//
function/S ValueErrorString(value, error, [delta, format, expformat, nonmetric])
variable value, error, delta
string format, expformat
variable nonmetric
 
// set defaults for possibly missing parameters
	if( ParamIsDefault(delta) )
		delta = error
	endif
	if( ParamIsDefault(format) )
		format = "v(e) "
	endif
	if( ParamIsDefault(expformat) )
		expformat = "x 10\S%d\M "
	endif
	if( ParamIsDefault(nonmetric) )
		nonmetric = 0
	endif
 
// calculate and preformat exponent
	variable prec = floor(log(abs(delta))), eng = ceil(prec/3), digits
	string pref, result
	if( nonmetric || (eng < -5) || (eng > 4) )
		variable prec1 = floor(log(abs(value)))	// added to give normal form n.nnn(nn) Enn
		sprintf pref, expformat, prec1
		eng = prec1 / 3
		digits = prec1 - prec
	else
		pref = "fpnµm.kMGT"[5+eng]
		if( !cmpstr(pref, ".") )
			pref = ""
		endif
		digits = 3*eng - prec
	endif
	value *= 10^(-3*eng)
	error *= 10^(-3*eng)
	string digstr = num2istr(digits)
 
// parse format, set defaults
	if( strsearch(format, "v", 0) < 0 )
		format = "v" + format
	endif
	if( strsearch(format, "e", 0) < 0 )
		format += "(±e) "
	endif
 
// print value
	format = ReplaceString("v", format, "%."+digstr+"f")
 
// case 1: error is non-zero (full format)
	if( error != 0 )
		if( strsearch(format, "±", 0) < 0 )	// special error format, zap zeros
			format = ReplaceString("e", format, "@%."+digstr+"f@")	// mark error value with "@"
		else
			format = ReplaceString("e", format, "%."+digstr+"f")
		endif
		format += "%s"
// print whole string
		sprintf result, format, value, error, pref
 
// treat special error format: zap leading zeros, including possible decimal point
		variable errpos = strsearch(result, "@", 0), nextchar
		if( errpos >= 0 )
			do
				errpos += 1
				nextchar = char2num(result[errpos])
				if( (nextchar == 64) || (errpos > strlen(result)) )	// "@" = 64 marks the end
					break
				endif
				// replace 0 or . from front with @ until something else is encountered
				if( (nextchar == 46) || (nextchar == 48) )
					result[errpos, errpos] = "@"
				else
					break
				endif
			while( 1 )
			result = ReplaceString("@", result, "")	// zap all "@"
			result = ReplaceString("()", result, "")	// zap brackets if they are empty
		endif
 
// case 2: error is zero (abbreviated format)
	else	// remove all elements pertaining to error
		format = ReplaceString(" e", format, "")	// try removing "e" placeholder with leading space
		format = ReplaceString("e", format, "")	// remove "e" place holder anyway
		format = ReplaceString(" ±", format, "")	// try removing "±" with leading space
		format = ReplaceString("±", format, "")	// remove "±" anyway
		format = ReplaceString("(", format, "")	// remove brackets
		format = ReplaceString(")", format, "")
		format += "%s"
// print whole string
		sprintf result, format, value, pref
	endif
	return result
end

Back to top