Skip to content

Instantly share code, notes, and snippets.

@telatin
Last active June 7, 2022 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save telatin/79f2eae9b061cbb8a818e66c58feb2e5 to your computer and use it in GitHub Desktop.
Save telatin/79f2eae9b061cbb8a818e66c58feb2e5 to your computer and use it in GitHub Desktop.
Procedure to add a thousands separator to a float [nim]
# https://forum.nim-lang.org/t/8162#52466
import strutils
proc floatSeparator(f: float, s=","): string =
var s = ($f).split('.')
s[0] = s[0].insertSep(',')
return s.join(".")
let
nums = @[112122.2, 12121.0, 902112.294, 41240.2, 20.0281]
for i in nums:
echo i.floatSeparator()
#[
112,122.2
12,121.0
902,112.294
41,240.2
20.0281
]#
# -------------
import math
import strformat
# ----------------------------------------------------------------------------------------------------------------------
proc fmtFloat*(value : float,
decimals : int,
format : string = "",
thousandSep: string = ",",
decimalSep : string = "."): string =
if value != value:
return "NaN"
elif value == Inf:
return "Inf"
elif value == NegInf:
return "-Inf"
let
forceSign = format.find('s') >= 0
thousands = format.find('t') >= 0
removeZero = format.find('z') >= 0
var valueStr = ""
if decimals >= 0:
valueStr.formatValue(round(value, decimals), "." & $decimals & "f")
else:
valueStr = $value
if valueStr[0] == '-':
valueStr = valueStr[1 .. ^1]
let
period = valueStr.find('.')
negZero = 1.0 / value == NegInf
sign = if value < 0.0 or negZero: "-" elif forceSign: "+" else: ""
var
integer = ""
integerTmp = valueStr[0 .. period - 1]
decimal = decimalSep & valueStr[period + 1 .. ^1]
if thousands:
while true:
if integerTmp.len > 3:
integer = thousandSep & integerTmp[^3 .. ^1] & integer
integerTmp = integerTmp[0 .. ^4]
else:
integer = integerTmp & integer
break
else:
integer = integerTmp
while removeZero:
if decimal[^1] == '0':
decimal = decimal[0 .. ^2]
else:
break
if decimal == decimalSep:
decimal = ""
return sign & integer & decimal
# ----------------------------------------------------------------------------------------------------------------------
when isMainModule:
doAssert fmtFloat( 0.0, 0) == "0"
doAssert fmtFloat(-0.0, 0) == "-0"
doAssert fmtFloat( 0.0, 0, "s") == "+0"
doAssert fmtFloat( 0.0, 0, "stz") == "+0"
doAssert fmtFloat(-0.0, 0, "s") == "-0"
doAssert fmtFloat(-0.0, 0, "stz") == "-0"
doAssert fmtFloat( 0.0, 2) == "0.00"
doAssert fmtFloat(-0.0, 2) == "-0.00"
doAssert fmtFloat( 0.0, 2, "s") == "+0.00"
doAssert fmtFloat(-0.0, 2, "s") == "-0.00"
doAssert fmtFloat( 0.0, 2, "sz") == "+0"
doAssert fmtFloat(-0.0, 2, "sz") == "-0"
doAssert fmtFloat(12_000.758, 0) == "12001"
doAssert fmtFloat(12_000.758, 0, "t") == "12,001"
doAssert fmtFloat(12_000.758, 0, "st") == "+12,001"
doAssert fmtFloat(12_000.758, 0, "stz") == "+12,001"
doAssert fmtFloat(12_000.758, 2) == "12000.76"
doAssert fmtFloat(12_000.758, 2, "t") == "12,000.76"
doAssert fmtFloat(12_000.758, 2, "st") == "+12,000.76"
doAssert fmtFloat(12_000.758, 2, "st", ".", ",") == "+12.000,76"
doAssert fmtFloat(12_000.758, 5, "t") == "12,000.75800"
doAssert fmtFloat(12_000.758, 5, "st") == "+12,000.75800"
doAssert fmtFloat(12_000.758, 5, "stz") == "+12,000.758"
doAssert fmtFloat(10_000_000.0, 2, "t") == "10,000,000.00"
doAssert fmtFloat(10_000_000.0, 2, "st") == "+10,000,000.00"
doAssert fmtFloat(10_000_000.0, 2, "tz") == "10,000,000"
doAssert fmtFloat(10_000_000.0, 2, "stz") == "+10,000,000"
doAssert fmtFloat(-5_000.12345, 0) == "-5000"
doAssert fmtFloat(-5_000.12345, 0, "t") == "-5,000"
doAssert fmtFloat(-5_000.12345, -1) == "-5000.12345"
doAssert fmtFloat(-5_000.12345, -1, "t") == "-5,000.12345"
doAssert fmtFloat(-5_000.12345, -1, "tz") == "-5,000.12345"
doAssert fmtFloat(NaN, 0) == "NaN"
doAssert fmtFloat(Inf, 1) == "Inf"
doAssert fmtFloat(NegInf, -1) == "-Inf"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment