3
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?

More than 1 year has passed since last update.

C#、BigintegerにSI接頭語をつける拡張メソッドを追加

Last updated at Posted at 2023-09-13

はじめに

クリッカーゲームなどで使う、桁数が増えた場合に1.0Kの様に途中の桁をSI接頭語に変換する拡張メソッドをC#で作りたかったので、桁数とSIを調査する

Bigintegerについて

任意の大きさの整数を表すための型であり、以下のような特徴がある

  • 任意の大きさの整数: BigInteger は、通常の整数型(int, long など)が持つ固定のサイズ制限を持たないため、非常に大きな整数値も表現できます。変換時に小数点以下は切り捨てられるので注意
BigInteger assignedFromDouble = (BigInteger) 179032.6541;
Console.WriteLine(assignedFromDouble);
BigInteger assignedFromDecimal = (BigInteger) 64312.65m;
Console.WriteLine(assignedFromDecimal);
// The example displays the following output:
//   179032
//   64312
  • 動的なサイズ: BigInteger のサイズは動的に変化し、必要に応じてメモリを確保します。このため、非常に大きな数を扱う場合には、それに伴ってメモリ使用量も増加します。typeScriptの
  • 不変性: BigInteger は不変型 (immutable) です。したがって、一度 BigInteger オブジェクトが作成されると、その値を変更することはできません。代わりに、新しい BigInteger オブジェクトが返されます。
  • パフォーマンス: 通常の整数型と比べると、BigInteger の計算は遅くなり得ます。特に非常に大きな数の演算を行う場合、計算時間やメモリ使用量が増加することを考慮する必要があります。

SI接頭語とは

k(キロ)、M(メガ)、G(ギガ)、m(ミリ)、µ(マイクロ)、n(ナノ)など、大きな量あるいは小さな量を端的に記述するために、10のべき乗を表し、SI単位と共に用いられるものをSI接頭語と呼びます。

トピックとして、割と最近(2022年)にクエタ(10^30),ロナ(10^27)が正式に加わっている

接頭語 記号 10n 十進数表記 漢数字表記 short scale メートル法への導入年 国際単位系における制定年
クエタ (quetta) Q 10^30 1000000000000000000000000000000 百穣 nonillion 2022年 -
ロナ (ronna) R 10^27 1000000000000000000000000000 千𥝱 octillion 2022年 -
ヨタ (yotta) Y 10^24 1000000000000000000000000 一𥝱 septillion 1991年 -
ゼタ (zetta) Z 10^21 1000000000000000000000 十垓 sextillion 1991年 -
エクサ (exa) E 10^18 1000000000000000000 百京 quintillion 1975年 -
ペタ (peta) P 10^15 1000000000000000 千兆 quadrillion 1975年 -
テラ (tera) T 10^12 1000000000000 一兆 trillion 1960年 -
ギガ (giga) G 10^9 1000000000 十億 billion 1960年 -
メガ (mega) M 10^6 1000000 百万 million 1874年 1960年
キロ (kilo) k 10^3 1000 thousand 1795年 1960年

以上を踏まえてコーディング

using System.Numerics;

namespace Sample
{
    /// <summary>
    /// SI接頭語の指数(10^nのnの部分)
    /// </summary>
    public enum SiPrefixesPowerExponent
    {
        Q = 30,
        R = 27,
        Y = 24,
        Z = 21,
        E = 18,
        P = 15,
        T = 12,
        G = 9,
        M = 6,
        K = 3,
    }

    public static class BigIntegerExtensions
    {
        /// <summary>
        /// BigIntegerの桁数を取得する
        /// マイナスの場合は絶対値に変換して桁数を返却する
        /// </summary>
        public static int GetNumberOfDigits(this BigInteger self)
        {
            return BigInteger.Abs(self).ToString().Length;
        }

        /// <summary>
        /// SI接頭語を付けた文字列に変換する
        /// </summary>
        public static string ToSiPrefixString(this BigInteger self)
        {
            var numberOfDigit = self.GetNumberOfDigits();
            var siPrefix = "";
            var displayIntegerLenght = 0; // 実数部分の表示範囲
            var displayDecimalLenght = 2; // 少数部分の表示範囲

            switch (numberOfDigit)
            {
                case < 4:
                    // 1000未満の場合は変換しない
                    return self.ToString();
                case > (int)SiPrefixesPowerExponent.Q + 3:
                    // SI接頭語の範囲外だった場合の表示対応
                    displayIntegerLenght = 1;
                    siPrefix = $" * 10^{numberOfDigit}";
                    break;
                default:
                {
                    var remainder = numberOfDigit % 3;
                    displayIntegerLenght = remainder == 0 ? 3 : remainder;
                    siPrefix = $"{(SiPrefixesPowerExponent)numberOfDigit - displayIntegerLenght}";
                    break;
                }
            }

            var displayString = self
                .ToString()
                .Substring(self.Sign == -1 ? 1 : 0, displayIntegerLenght + displayDecimalLenght) //マイナスの場合は"-"部分を飛ばす
                .Insert(displayIntegerLenght, ".");

            return self > 0 ? $"{displayString}{siPrefix}" : $"-{displayString}{siPrefix}";
        }
    }
}

おわりに

Bigintegerの計算は単純にインクリメントするだけでもそこそこになるらしく、ループ内で使用したい場合などはパフォーマンスに無視できない負荷がかかるらしいので、注意したい

参考

https://ja.wikipedia.org/wiki/SI%E6%8E%A5%E9%A0%AD%E8%AA%9E
https://unit.aist.go.jp/nmij/library/SI_prefixes/

3
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
3
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?