Stevin's Notation is a way to represent decimals in a non-fractional way.

The Flemish mathematician and engineer Simon Stevin is remembered for his study of decimal fractions. Although he was not the first to use decimal fractions (they are found in the work of the tenth-century Islamic mathematician al-Uqlidisi), it was his tract De Thiende (“The tenth”), published in 1585 and translated into English as Disme: The Art of Tenths, or Decimall Arithmetike Teaching (1608),[3] that led to their widespread adoption in Europe. Stevin, however, did not use the notation we use today. He drew circles around the exponents of the powers of one tenth: thus he wrote 7.3486 as 7⓪3①4②8③6④.

For example, the decimal number 32.567 can be expressed as 32 + 5/10 + 6/100 + 7/1000. In Stevin's Notation, circled numbers representing the denominator of the original decimal fraction were inserted after each number.

In lieu of formatting the output via parenthesis or using any unicode characters, we will simply output the associated power of ten number.

Therefore, the decimal number above would be written as 320516273.


When given a decimal input, output a Stevin's Notation integer equivalent.


  • For any input containing trailing 0 after the decimal point, the author can choose whether or not to include the zeroes as part of their output notation. This holds true for multiple trailing zeroes as well.
    • This means for the input 1.0500, either of the following output would be acceptable: 100152 or 1001520304
  • For any input with no decimal point, or any input containing only zeroes after the decimal point, the author may choose to simply output the integer equivalent.
    • This means for the input 123, either of the following output would be acceptable: 123, 1230.
    • This also means for the input 123.0, any of the following output would be acceptable: 123, 1230, 123001.
  • For this challenge, we can assume the input will be positive.

Test cases:

Input Output
123 123 or 1230
123.0 123 or 1230 or 123001
123.00000 123 or 1230 or 12300102030405
123.456 1230415263
123.456000 1230415263 or 1230415263040506
1.000009 10010203040596
0 0 or 00
0.0 0 or 00 or 0001
0.0001 0001020314
123456789.123456789987654321 1234567890112233445566778899910811712613514415316217118

This is , so shortest code in bytes wins!

  • 2
    \$\begingroup\$ can input be a list of digits or the like, or does it have to be a float? \$\endgroup\$
    – Jonah
    Aug 23, 2023 at 22:29
  • 9
    \$\begingroup\$ Why are the first 3 test cases not 1230? \$\endgroup\$
    – Shaggy
    Aug 23, 2023 at 22:48
  • 2
    \$\begingroup\$ Please could you clarify: (1) "Inputs containing trailing 0 can be omitted from output." = does this mean that we can choose whether or not to omit trailing zeros? (2) "I chose to ignore ... inclusion of the initial zero" = must we also ignore inclusion of the initial zero, or may we choose to include it? \$\endgroup\$ Aug 24, 2023 at 9:25
  • \$\begingroup\$ Thanks for the feedback, everyone. The question has been updated for clarity. \$\endgroup\$
    – CzarMatt
    Aug 29, 2023 at 21:03

10 Answers 10


JavaScript (ES6), 64 bytes

Expects a string as input.


Try it online!


We first look for the fractional part in the input string:

  .---------> decimal separator
  |  .------> payload: a non-greedy sequence of digits
  |  |   .--> trailing zeros + end of string
  | _|_  |
  |/   \/ \

If the payload is empty, we remove the fractional part entirely.

Otherwise, we replace the fractional part with the payload transformed as follows:

s.replace(  // in the payload,
  /()/g,    // replace each gap (beginning and end included)
  _ => i++, // with the counter i (incremented afterwards)
  i = 0     // starting with i = 0
)           //

Retina, 33 bytes



Try it online! Link includes test cases. Explanation:


If the input contains a decimal point, trim any trailing zeros and also the decimal point if there are only trailing zeros (in which case the rest of the script will do nothing).


Number each character starting at the decimal point.


Remove the decimal point.


sclin, 46 bytes

99N>d"\."<>"len1>"Q";".' &# c><
0swap $N","zip

Try it here!

For testing purposes:

7.3486 ;
99N>d"\."<>"len1>"Q";".' &# c><
0swap $N","zip


Prettified code:

99N>d "\."<> ( len 1> ) Q \;.' &# c><
0swap $N \, zip
  • 99N>d convert input to decimal representation
    • necessary to get around sclin's default rational representation, and also to remove trailing zeros (unless spec is more lenient)
  • "\."<> split by decimal point
  • ( len 1> ) Q \;.' &# if length > 1 (i.e. decimal values exist), then...
    • 0swap place zero as "decimal"
    • $N \, zip enumerate
  • c>< join
    • NOTE: this might be removable if a jagged list is allowed as an output format - e.g. [123 0 [ 5 1 6 2 ]]

Perl 5 (-p), 36 bytes


Works the same as Arnauld's Javascript answer

Try it online!


Charcoal, 23 bytes


Try it online! Link is to verbose version of code. Explanation:

  S                     Input string
 ⪪                      Split on
   .                    Literal string `.`
⭆                       Map over parts and join
     κ                  Current index
    ⎇                   If decimal part then
        ι               Decimal part
       Σ                Digital sum
      ⎇                 If nonzero then
          0             Literal string `0`
         ⁺              Concatenated with
                ι       Decimal part
               ⮌        Reversed
              I         Cast to integer
             I          Cast to string
            ⮌           Reversed
           ⭆            Map over characters and join
                  λ     Current character
                 ⁺      Concatenated with
                    μ   Inner index
                   ⊕    Incremented
                     ω  Otherwise empty string
                      ι Otherwise integer part
                        Implicitly print

Vyxal d, 78 bitsv2, 9.75 bytes


Try it Online!


\.+\./        # ‎⁡Append a "." to the input and split on "."s
      ḣh      # ‎⁢that[0], that[1]
        fJ    # ‎⁣flatten(that[1]) and merge with that[0]
          ėR  # ‎⁤Enumerate and reverse each sublist
# ‎⁢⁡d flag deep sums the list

Created with the help of Luminespire.


Python, 77 bytes

lambda x,i=0:(s:=x.partition("."))[0]+'0'+''.join(c+str(i:=i+1)for c in s[2])

Attempt This Online!


Thunno 2 J, 13 bytes


Try it online!

Input as a string.


'.+'./2ɱẸsƤŻZ  # Implicit input
'.+           '# Append a "." in case it isn't there already
   './        '# Then split it on "."s
      2ɱ       # And take the first two items
        Ẹ      # Dump both parts onto the stack
         sƤ    # Split the second part into characters and prepend the first part
           Ż   # Push [0..length] without popping this list
            Z  # And zip these two lists together
               # Implicit output, joined
  • 2
    \$\begingroup\$ I notice that in your link you've omitted some test-cases, and adjusted the output of others to match the (different) output of your answer. You may feel that the spec isn't unambiguously defined (and I have asked for clarification from the OP), but I think that adjusting the test case outputs so that you can give them green ticks and label them 'PASS' is a little fishy... \$\endgroup\$ Aug 24, 2023 at 10:07
  • \$\begingroup\$ @DominicvanEssen I wouldn't normally leave out test cases, but I saw that the Vyxal and Python answers have. This is basically just a port of the Python answer, so if this is invalid, that answer is also invalid. I adjusted the first test case output because, based on how I read the challenge, both outputs 123 and 1230 are valid. Anyway, hopefully the spec will be improved, and when it is, I will update this answer as necessary. \$\endgroup\$
    – The Thonnu
    Aug 24, 2023 at 10:13
  • 1
    \$\begingroup\$ @DominicvanEssen the spec has now been updated. It turns out my initial assumption was actually correct, and so I didn't need to update the code. I have, however, now added in all of the test cases to my TIO link. \$\endgroup\$
    – The Thonnu
    Aug 28, 2023 at 17:41

Nibbles, 8.5 bytes (17 nibbles)


Attempt This Online!

Outputs a trailing zero after integers (as permitted), and retains trailing zeros after the decimal point.

Nibbles, 10 bytes (20 nibbles)


Attempt This Online!

No trailing zero after integers, but retains trailing zeros after the decimal point.

  %$"."             # split the input string on "."
`(                  # and output the first part
       ?,$          # now, if there's second part 
             !+$    # zip it together with
                ,~  # 1..infinity
                  : # by concatenation,
           :0       # prepend a zero
                    # and output it after the first part

Nibbles, 14.5 bytes (29 nibbles)


Attempt This Online!

Outputs according to the initial test cases: no trailing zero for integers, no trailing zeros after the decimal point.


Scala, 93 bytes

Port of @SuperStormer's Python answer in Scala.

Golfed version. Try it online!


Ungolfed version. Try it online!

object Main {
  def f(x: String, i: Int = 0): String = {
    val parts = x.split("\\.")
    val s = parts(1).toList.zipWithIndex.map { case (c, idx) => c.toString + (i + idx + 1).toString }.mkString
    parts(0) + "0" + s

  def main(args: Array[String]): Unit = {
    println(f("123.456") == "1230415263")
    println(f("0.0001") == "0001020314")
    println(f("123456789.123456789987654321") == "1234567890112233445566778899910811712613514415316217118")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.