0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PostgreSQL 18がやってくる(10) Add roman support for to_number function

Last updated at Posted at 2025-05-06

はじめに

にゃーん。
楽しい5月連休も今日が最終日。残念ながら明日からは仕事をしなければなりません。

今日は小ネタ。TO_NUMBER/TO_CHARでローマ数字をサポートした、というものです。
平たい顔属なので、普段はあまり使わない(映画やゲームのナンバリングくらいでしか使わない?)ローマ数字ですが、PostgreSQLでも今まではサポートしてなかったようです。

概要

Commitfest 2025-01でコミットされた項目である。

タイトル Add roman support for to_number function
Topic Performance
Created 2024-08-30 07:22:58
Last modified 2025-01-22 20:20:02
Emails [PATCH] Add roman support for to_number function

PostgreSQL 18での改善内容

PostgreSQL 18では以下の機能が追加された。

  • TO_NUMBER関数で、ローマ数字から数値への変換が可能になった。
  • TO_CHAR関数で数値からローマ数字への変換が可能になった。

TO_NUMBER()

ローマ数字から数値に変換する場合には、TO_NUMBERの第2引数にRNまたはFMRNを指定する。
ただ、TO_NUMBERの場合には、ローマ数字文字列をtrimしてから処理するっぽいので、RNを指定してもFMRNを指定しても効果は変わらないようだ。

postgres=# SELECT to_number('I', 'RN');
 to_number
-----------
         1
(1 row)

postgres=# SELECT to_number('I', 'FMRN');
 to_number
-----------
         1
(1 row)

postgres=# SELECT to_number('    I      ', 'RN');
 to_number
-----------
         1
(1 row)

postgres=# SELECT to_number('    I      ', 'FMRN');
 to_number
-----------
         1
(1 row)

他のローマ数字の例も試してみる(フォーマット指定はRNのみ試行)。

postgres=# SELECT to_number('XVIII','RN');
 to_number
-----------
        18
(1 row)

postgres=# SELECT to_number('xvIIi','RN');
 to_number
-----------
        18
(1 row)

postgres=# SELECT to_number('CCCXXXIV','RN');
 to_number
-----------
       334
(1 row)

postgres=# SELECT to_number('MMMCMXCIX','RN');
 to_number
-----------
      3999
(1 row)

ローマ数字のアルファベットは大文字も小文字も(混在しても)指定可能である。

正負記号(+-)を頭につけた場合はエラーになる。
数字文字列途中にローマ数字で規定された英文字(I,V,X,L,C,D,M)が含まれていた場合には、そこまでの文字列を元に数値への変換を行う。

postgres=# SELECT to_number('CCCXXXIV','RN');
 to_number
-----------
       334
(1 row)

postgres=# SELECT to_number('-CCCXXXIV','RN');
ERROR:  invalid Roman numeral
postgres=# SELECT to_number('+CCCXXXIV','RN');
ERROR:  invalid Roman numeral
postgres=# SELECT to_number('CCC.XXXIV','RN');
 to_number
-----------
       300
(1 row)

postgres=# SELECT to_number('CCC XXXIV','RN');
 to_number
-----------
       300
(1 row)

TO_CHAR()

数値からローマ数字に変換する場合には、TO_CHARの第2引数にRNまたはFMRNを指定する。

  • RNを指定した場合は、右詰め文字列となる。
  • FMRNを指定した場合、左詰め文字列となる。
postgres=# SELECT to_char(1, 'RN');
     to_char
-----------------
               I
(1 row)

postgres=# SELECT to_char(1, 'FMRN');
 to_char
---------
 I
(1 row)

postgres=# SELECT to_char(334, 'RN');
     to_char
-----------------
        CCCXXXIV
(1 row)

postgres=# SELECT to_char(334, 'FMRN');
 to_char
----------
 CCCXXXIV
(1 row)

postgres=# SELECT to_char(3999, 'RN');
     to_char
-----------------
       MMMCMXCIX
(1 row)

postgres=# SELECT to_char(3999, 'FMRN');
  to_char
-----------
 MMMCMXCIX
(1 row)

ローマ数字の範囲って?

そういえばローマ数字の範囲ってどうなっている?と思い。Wikpedia記事(ローマ数字)を見てみた。

現代の一般的な表記法では、1以上4000未満の数を表すことができる。

とのこと。

では、TO_CHAR()の第1引数に、0、負の数、小数、4000以上の数、を指定したらどうなるのか。

postgres=# SELECT to_char(0, 'RN');
     to_char
-----------------
 ###############
(1 row)

postgres=# SELECT to_char(-1, 'RN');
     to_char
-----------------
 ###############
(1 row)

postgres=# SELECT to_char(3.4, 'RN');
     to_char
-----------------
             III
(1 row)

postgres=# SELECT to_char(3.5, 'RN');
     to_char
-----------------
              IV
(1 row)

postgres=# SELECT to_char(3999, 'RN');
     to_char
-----------------
       MMMCMXCIX
(1 row)

postgres=# SELECT to_char(4000, 'RN');
     to_char
-----------------
 ###############
(1 row)
  • 0や負数、4000以上の数字を指定した場合はエラーにならず###############という文字列が返却される。
    • TO_NUMBERでフォーマットに誤りが合った場合にはエラーになるが、TO_CHAR()ではエラーにならない。これは他のTO_CHAR()の流儀に倣ったものなのだろう。
  • 小数を指定した場合には、それをROUND()した結果をローマ数字に変換する(実際にコードを確認したわけでなく挙動からの推測)。

おわりに

大昔、自分もksjという漢数字型を扱えるジョーク定義型を作ったことがある1ので、こういう変な(?)数値記法を可能にする改善は面白いなあと思っています。

Make Roma Great Again!

  1. 全然メンテナンスしていないのでたぶん、最近の環境だとビルドできないと思う・・・申し訳ない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?