.NETで、桁数と精度を指定してランダムな数値を生成する
はじめに
桁数と精度を指定してランダムな数値を生成するメソッドの、.NET(C#)での実装例を示す。
補足説明
「桁数」と「精度」というのは、OracleのNUMBER型で指定する、NUMBER(p, s)の
- p:桁数
- s:精度
のこと。NUnitなどを使ったユニットテストで、OracleのNUMBER型のフィールドに、ランダムな数値を設定したい、といった用途が*1想定される。
以下の実装例だと、戻り値が必ず0以上の数となる。戻り値に負の数も現れるようにするためには、もうひと工夫が必要。
コメント
以下の実装例、なんだかとっても重たそうですね…。でも、私にはこれしか思いつきませんでした。別のもっと良いアイデア、募集中です!!
※ビット演算とか使った、すげぇやつを見てみたい(。-_-。)
あと、以下の実装例が間違ってる可能性もあります。間違いのご指摘、歓迎です!!
実装例1 - ユーティリティメソッドとして…
/// <summary> /// <c>0</c> 以上、かつ指定された桁数、および精度で表せる最大の数以下の、 /// ランダムな <see cref="Double"/> 値を返す。 /// </summary> /// <param name="precision">戻り値の桁数。</param> /// <param name="scale">戻り値の精度。</param> /// <returns>ランダムな <see cref="Double"/> 値。</returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="precision"/> に <c>0</c> 以下の数が指定された。 /// </exception> /// <remarks> /// <paramref name="scale"/> に <c>0</c> を指定することで、 /// 戻り値が整数となる。 /// </remarks> public static double GetRandomDouble(int precision, int scale) { if (precision <= 0) { throw new ArgumentOutOfRangeException("precision", precision, "0 より大きい数を指定してください。"); } var value = Math.Pow(10, precision) * __random.NextDouble(); value = Math.Truncate(value); value /= Math.Pow(10, scale); return value; } /// <summary> /// <see cref="GetRandomDouble"/> メソッドが使用する乱数ジェネレータ。 /// </summary> private static readonly Random __random = new Random();
実装例2 - C# 3.0から使える拡張メソッドを使って…
/// <summary> /// <c>0</c> 以上、かつ指定された桁数、および精度で表せる最大の数以下の、 /// ランダムな <see cref="Double"/> 値を返す。 /// </summary> /// <param name="random">疑似乱数ジェネレータ。</param> /// <param name="precision">戻り値の桁数。</param> /// <param name="scale">戻り値の精度。</param> /// <returns>ランダムな <see cref="Double"/> 値。</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="random"/> に <c>null</c> が指定された。 /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="precision"/> に <c>0</c> 以下の数が指定された。 /// </exception> /// <remarks> /// <paramref name="scale"/> に <c>0</c> を指定することで、 /// 戻り値が整数となる。 /// </remarks> public static double NextDouble(this Random random, int precision, int scale) { if (random == null) { throw new ArgumentNullException("random"); } if (precision <= 0) { throw new ArgumentOutOfRangeException("precision", precision, "0 より大きい数を指定してください。"); } var value = Math.Pow(10, precision) * random.NextDouble(); value = Math.Truncate(value); value /= Math.Pow(10, scale); return value; }
*1:ニッチですねー