web-dev-qa-db-ja.com

10進数をゼロではない最初の小数点以下の桁数に丸めます

数値を0ではない最初の有効桁に短縮したい。後ろの桁は四捨五入する必要があります。

例:

0.001 -> 0.001
0.00367 -> 0.004
0.00337 -> 0.003
0.000000564 -> 0.0000006
0.00000432907543029 ->  0.000004

現在、次の手順があります。

if (value < (decimal) 0.01)
{
    value = Math.Round(value, 4);
}

注意:

  • 数字は常に正になります
  • 有効桁数は常に1になります
  • 0.01より大きい値は、常に小数点以下2桁に丸められるため、<0.01の場合

上記の例からわかるように、小数点以下4桁に丸めるだけでは不十分で、値が大きく異なる場合があります。

19
julian bechtold

precision変数を宣言し、反復を使用して、その変数に10を掛け、ヒットしなかった元の値を掛けます。precision1を追加します。

次に、precision変数をMath.Round2番目のパラメーターとして使用します。

static decimal RoundFirstSignificantDigit(decimal input) {
    int precision = 0;
    var val = input;
    while (Math.Abs(val) < 1)
    {
        val *= 10;
        precision++;
    }
    return Math.Round(input, precision);
}

この関数の拡張メソッドを作成します。

public static class FloatExtension
{
    public static decimal RoundFirstSignificantDigit(this decimal input)
    {
        int precision = 0;
        var val = input;
        while (Math.Abs(val) < 1)
        {
            val *= 10;
            precision++;
        }
        return Math.Round(input, precision);
    }
}

その後、次のように使用します

decimal input = 0.00001;
input.RoundFirstSignificantDigit();

c#オンライン

結果

(-0.001m).RoundFirstSignificantDigit()                  -0.001
(-0.00367m).RoundFirstSignificantDigit()                -0.004
(0.000000564m).RoundFirstSignificantDigit()             0.0000006
(0.00000432907543029m).RoundFirstSignificantDigit()     0.000004
17
D-Shih

そんな感じ ?

    public decimal SpecialRound(decimal value) 
    {
        int posDot = value.ToString().IndexOf('.'); // Maybe use something about cultural (in Fr it's ",")
        if(posDot == -1)
            return value;

        int posFirstNumber = value.ToString().IndexOfAny(new char[9] {'1', '2', '3', '4', '5', '6', '7', '8', '9'}, posDot);

        return Math.Round(value, posFirstNumber);
    }
2
Benjamin K

コードはRからのものですが、アルゴリズムは明白である必要があります

> x = 0.0004932
> y = log10(x)
> z = ceiling(y)
> a = round(10^(y-z),1)
> finally = a*10^(z)
> finally
[1] 5e-04

以下は基本的にすでにベンジャミンKによって提供されました

完全なワッコとラベル付けされるリスクを冒して、私はregexpがあなたの友達であることを陽気に発表します。数値を文字列に変換し、「。」でもない最初の文字の場所を検索します。また、「0」、その場所の文字とその後ろの次の文字を取得し、それらを数値に変換して丸め、結果に$ 10 ^ {-(間に見つかったゼロの数)を掛けます。 。 "と最初の数字)} $

1
Carl Witthoft
var value = 0.000000564;

int cnt = 0;
bool hitNum = false;
var tempVal = value;
while (!hitNum)
{
    if(tempVal > 1)
    {
        hitNum = true;
    }
    else
    {
        tempVal *= 10;
        cnt++;
    }
}

var newValue = (decimal)Math.Round(value, cnt);
1
ManishM

別のアプローチ

    decimal RoundToFirstNonNullDecimal(decimal value)
    {
        var nullDecimals = value.ToString().Split('.').LastOrDefault()?.TakeWhile(c => c == '0').Count();
        var roundTo = nullDecimals.HasValue && nullDecimals >= 1 ? nullDecimals.Value + 1 : 2;
        return Math.Round(value, roundTo);
    }

結果

        Console.WriteLine(RoundToFirstNonNullDecimal(0.001m));                0.001
        Console.WriteLine(RoundToFirstNonNullDecimal(0.00367m));              0.004
        Console.WriteLine(RoundToFirstNonNullDecimal(0.000000564m));          0.0000006
        Console.WriteLine(RoundToFirstNonNullDecimal(0.00000432907543029m));  0.000004
        Console.WriteLine(RoundToFirstNonNullDecimal(0.12m));                 0.12
        Console.WriteLine(RoundToFirstNonNullDecimal(1.232m));                1.23
        Console.WriteLine(RoundToFirstNonNullDecimal(7));                     7.00
0
crazy_p