How to suppress trailing zeros when displaying decimals?

I would like to find an option to suppress the output of trailing zeros when displaying decimals, preferrably using oxifmt. Given this definition:

#let a = decimal("220000")
#let b = decimal("220000.0")
#let c = decimal("220000.00")

(a: #a, b: #b, c: #c)

effe
I would love to find the way to diplay a, b, and c as 220000.

As Decimal Type – Typst Documentation says:

To only display a certain number of digits, round the decimal first.


#let a = decimal("220000")
#let b = decimal("220000.0")
#let c = decimal("220000.00")

(a: #calc.round(a), b: #calc.round(b), c: #calc.round(c))

图片

Sorry for not being clear enough. I only want the trailing zeroes to be suppressed, I don’t want to lose precision. Thus:

#let a = decimal("220000.00")
#let b = decimal("220000.90")
#let c = decimal("220000.99")

(a: #fmt(a), b: #fmt(b), c: #fmt(c))

Should output

(a: 220000, b: 220000.9, c: 220000.99)

The question is, how can I write fmt?

1 Like

I see; maybe this?

#let fmt(x) = str(x).replace(regex("\.?0+$"), "")
A comic

xkcd: Regular Expressions

Regexes kind of work, as they always do, until they don’t. Your solution deletes all zeroes at the end of a number. #fmt(200) becomes 2.

I’d really like a solution that integrates with oxifmt because I want to use its fmt-thousands-separator and fmt-decimal-separator, and also because I feel it kind of is the way to go until Typst gets proper string formatting.

1 Like

OK, so I filed a feature request to oxifmt but looking further into this, I think this is actually a Typst bug. Typst should convert a decimal to a string in the shortest possible way, not in the way the number was input. I think the following is wrong:

#let a = decimal("200")
#let b = decimal("200.0")

(a: #a, b: #b)

Naked comparison: a == b: #{a == b}

String comparison: str(a) == str(b): #{str(a) == str(b)}

Thoughts?

(At this moment, it’s already possible to extend the number of trailing zeroes to a common displayed precision by using oxifmt)

1 Like

It seems it works as designed? From Decimal Type – Typst Documentation

This constructor preserves all given fractional digits, provided they are representable as per the limits specified below (otherwise, an error is raised).

You could always ask in GitHub · Where software is built or Discord if you wanted to suggest changes to the current design.

I don’t know if I want to raise an issue for this, I can kind of see that keeping the digits might be handy in some circumstances. In the meantime, I learned that removing these trailing fractional zeroes is called normalisation. I also found a more robust way to do this that returns a new decimal:

#let normalize(dec) = {
  let ipart = calc.trunc(dec)
  let fpart = calc.fract(dec)
  if fpart == 0 {
    return ipart 
  } else {
    fpart = decimal(str(fpart).trim("0",at:end,repeat:true))
    return ipart + fpart
  }
}
2 Likes