diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 5ba8a6fd5..be80685ab 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -14,6 +14,7 @@ ## `_. import parseutils +from math import pow, round, floor, log10 {.deadCodeElim: on.} @@ -1541,6 +1542,141 @@ proc formatSize*(bytes: int64, result &= prefixes[matchedIndex] result &= "B" +proc formatEng*(f: BiggestFloat, + precision: range[0..32] = 10, + trim: bool = true, + siPrefix: bool = false, + unit: string = nil, + decimalSep = '.'): string {.noSideEffect.} = + ## Converts a floating point value `f` to a string using engineering notation. + ## + ## Numbers in of the range -1000.0= 1000.0: + significand *= 0.001 + fexponent += 3 + # Components of the result: + result = significand.formatBiggestFloat(ffDecimal, precision, decimalSep='.') + exponent = fexponent.int() + + splitResult = result.split('.') + result = splitResult[0] + # result should have at most one decimal character + if splitResult.len() > 1: + # If trim is set, we get rid of trailing zeros. Don't use trimZeros here as + # we can be a bit more efficient through knowledge that there will never be + # an exponent in this part. + if trim: + while splitResult[1].endsWith("0"): + # Trim last character + splitResult[1].setLen(splitResult[1].len-1) + if splitResult[1].len() > 0: + result &= decimalSep & splitResult[1] + else: + result &= decimalSep & splitResult[1] + + # Combine the results accordingly + if siPrefix and exponent != 0: + var p = getPrefix(exponent) + if p != ' ': + suffix = " " & p + exponent = 0 # Exponent replaced by SI prefix + if suffix == "" and unit != nil: + suffix = " " + if unit != nil: + suffix &= unit + if exponent != 0: + result &= "e" & $exponent + result &= suffix + proc findNormalized(x: string, inArray: openArray[string]): int = var i = 0 while i < high(inArray): @@ -1864,4 +2000,33 @@ bar doAssert s.split(' ', maxsplit=4) == @["", "this", "", "", "is an example "] doAssert s.split(" ", maxsplit=4) == @["", "this", "", "", "is an example "] + block: # formatEng tests + doAssert formatEng(0, 2, trim=false) == "0.00" + doAssert formatEng(0, 2) == "0" + doAssert formatEng(53, 2, trim=false) == "53.00" + doAssert formatEng(0.053, 2, trim=false) == "53.00e-3" + doAssert formatEng(0.053, 4, trim=false) == "53.0000e-3" + doAssert formatEng(0.053, 4, trim=true) == "53e-3" + doAssert formatEng(0.053, 0) == "53e-3" + doAssert formatEng(52731234) == "52.731234e6" + doAssert formatEng(-52731234) == "-52.731234e6" + doAssert formatEng(52731234, 1) == "52.7e6" + doAssert formatEng(-52731234, 1) == "-52.7e6" + doAssert formatEng(52731234, 1, decimalSep=',') == "52,7e6" + doAssert formatEng(-52731234, 1, decimalSep=',') == "-52,7e6" + + doAssert formatEng(4100, siPrefix=true, unit="V") == "4.1 kV" + doAssert formatEng(4.1, siPrefix=true, unit="V") == "4.1 V" + doAssert formatEng(4.1, siPrefix=true) == "4.1" # Note lack of space + doAssert formatEng(4100, siPrefix=true) == "4.1 k" + doAssert formatEng(4.1, siPrefix=true, unit="") == "4.1 " # Includes space + doAssert formatEng(4100, siPrefix=true, unit="") == "4.1 k" + doAssert formatEng(4100) == "4.1e3" + doAssert formatEng(4100, unit="V") == "4.1e3 V" + doAssert formatEng(4100, unit="") == "4.1e3 " # Space with unit="" + # Don't use SI prefix as number is too big + doAssert formatEng(3.1e22, siPrefix=true, unit="a") == "31e21 a" + # Don't use SI prefix as number is too small + doAssert formatEng(3.1e-25, siPrefix=true, unit="A") == "310e-27 A" + #echo("strutils tests passed") diff --git a/web/news.txt b/web/news.txt index 2ede07151..12f08e5eb 100644 --- a/web/news.txt +++ b/web/news.txt @@ -70,6 +70,8 @@ Library Additions into an integer part and a floating part (in the range -1