1

Here is how my method is currently defined in Scala, i've been following this Stackoverflow answer

  def digitFormatter(long: Long, numDigits: Int): String = {
    String.format(s"%0${numDigits}d", long)
  }

This seems to work ok with postive integers, i get this expected behavior

    assert(digitFormatter(0, 1) == "0")
    assert(digitFormatter(0, 2) == "00")
    assert(digitFormatter(1, 2) == "01")
    assert(digitFormatter(10, 2) == "10")

However this doesn't seem to work with negative numbers, this is what I would expect my output to be

    assert(
      digitFormatter(-1, 2) == "-01")

However the result I get is just -1. How do I pad leading zeroes on negative numbers using the java std libraries?

Chris Stewart
  • 1,641
  • 2
  • 28
  • 60
  • 1
    @OHGODSPIDERS I think that's scala-ese for 'apply variable substitution and other templatey things to this string', and is what makes `${whatsit}` work. – rzwitserloot Nov 05 '20 at 12:36

4 Answers4

2

You've mischaracterised what String.format does. In your code, you have ${numDigits} which suggests you think that number in front of the d is the number of digits.

No, it's the number of characters.

In other words:

String.format("%05d", -12)

produces the string -0012, because you asked for a string which is at minimum 5 characters long, and which applies 0-padding to get to 5 characters.

If you want a method which turns e.g. -12 into -00012 (6 characters, 5 digits) and +12 into 00012 (5 characters, 5 digits), then you'd have to do something like:

def digitFormatter(long: Long, numDigits: Int): String = {
    var numChars = numDigits + (if (long < 0) 1 else 0)
    String.format(s"%0${numChars}d", long)
}

NB: I'm not a scala programmer, I'm taking a bit of a stab with that ternary operator, but I think you can do that in scala.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • this causes a runtime exception >java.util.DuplicateFormatFlagsException: Flags = '0' at java.util.Formatter$Flags.parse(Formatter.java:4443) at java.util.Formatter$FormatSpecifier.flags(Formatter.java:2640) at java.util.Formatter$FormatSpecifier.(Formatter.java:2709) at java.util.Formatter.parse(Formatter.java:2560) at java.util.Formatter.format(Formatter.java:2501) at java.util.Formatter.format(Formatter.java:2455) at java.lang.String.format(String.java:2940) – Chris Stewart Nov 05 '20 at 12:41
  • I've changed it to `String.format(s"%0${numChars + numDigits}d", long)` but it still doesn't work. `"-[]1" did not equal "-[0]1"` – Chris Stewart Nov 05 '20 at 12:42
  • @Chris use your scala skills, and try to understand the answer. If you ask for a minimum of 5 digits and toss -1 through there, your current code (without these updates) would print `-0001` - surely you can figure it out from there. I've updated the answer with what I think scala's ternary mode is. – rzwitserloot Nov 05 '20 at 13:03
  • That error indicates my original snippet was resulting in 'numChars' being 0, probably because of operator precedence. All you need is (). As a general tip, with scala, compiler errors are incredibly obtuse so you need to spend a little time trying to figure out what's happening before just giving up, because otherwise, scala isn't for you. – rzwitserloot Nov 05 '20 at 13:05
  • I don't want to say that scala errors are always perfect, but that error is coming from the Java runtime, not from the scala compiler. – Martijn Nov 06 '20 at 16:09
1

Unfortunately, there is no Java format available that does this: They format on total string width, not on number of zeroes. The easiest way is to vary the length of the padding depending on whether the argument is negative:

def digitFormatter(long: Long, numDigits: Int): String = {
  val padlength = if (long >= 0) numDigits else numDigits + 1
  String.format(s"%0${padlength}d", long)
}
Martijn
  • 11,964
  • 12
  • 50
  • 96
0

String.format should not be used at Scala. You can read the post The Scala String format approach (and Java String.format) by Alvin Alexander.

To make it work in Scala you need to do:

def digitFormatter(long: Long, numDigits: Int): String = {
  val padlength = if (long < 0) numDigits + 1 else numDigits
  s"%0${padlength}d".format(long)
}

You can find the format method in Scala docs. Code run can be found at Scastie.

Tomer Shetah
  • 8,413
  • 7
  • 27
  • 35
-1

You can do it just as below:

String result = ((value < 0) ? "-" : "") + String.format("%05d", Math.abs(value)); 
Mustafa Poya
  • 2,615
  • 5
  • 22
  • 36