簡體   English   中英

在十進制數字的n位置找到數字的最佳方法是什么?

[英]What is the best way to find the digit at n position in a decimal number?

背景

我正在進行一個對稱的舍入課程,我發現我對如何最好地找到x位置的數字感到困惑,我將會四舍五入。 我確信有一種有效的數學方法可以找到單個數字並返回它而不必求助於字符串解析。

問題

假設,我有以下(C#)偽代碼:

var position = 3;
var value = 102.43587m;
// I want this no ↑ (that is 5)

protected static int FindNDigit(decimal value, int position)
{
    // This snippet is what I am searching for
}

另外,值得注意的是,如果我的值是整數,我將需要為FindNDigit的結果返回零。

有沒有人對我應該如何處理這個問題有任何暗示? 這是一件非常明顯的事情嗎?

(int)(value * Math.Pow(10, position)) % 10

怎么樣:

(int)(double(value) * Math.Pow(10, position)) % 10

基本上你乘以10 ^ pos以便將該數字移動到一個位置,然后使用模數運算符%來除去數字的其余部分。

using System;

public static class DecimalExtensions
{
    public static int DigitAtPosition(this decimal number, int position)
    {
        if (position <= 0)
        {
            throw new ArgumentException("Position must be positive.");
        }

        if (number < 0)
        {
            number = Math.Abs(number);
        }

        number -= Math.Floor(number);

        if (number == 0)
        {
            return 0;
        }

        if (position == 1)
        {
            return (int)(number * 10);
        }

        return (number * 10).DigitAtPosition(position - 1);
    }
}

編輯 :如果您願意,您可以將遞歸調用與初始調用分開,以在遞歸期間刪除初始條件檢查:

using System;

public static class DecimalExtensions
{
    public static int DigitAtPosition(this decimal number, int position)
    {
        if (position <= 0)
        {
            throw new ArgumentException("Position must be positive.");
        }

        if (number < 0)
        {
            number = Math.Abs(number);
        }

        return number.digitAtPosition(position);
    }

    static int digitAtPosition(this decimal sanitizedNumber, int validPosition)
    {
        sanitizedNumber -= Math.Floor(sanitizedNumber);

        if (sanitizedNumber == 0)
        {
            return 0;
        }

        if (validPosition == 1)
        {
            return (int)(sanitizedNumber * 10);
        }

        return (sanitizedNumber * 10).digitAtPosition(validPosition - 1);
    }

這是一些測試:

using System;
using Xunit;

public class DecimalExtensionsTests
{
                         // digit positions
                         // 1234567890123456789012345678
    const decimal number = .3216879846541681986310378765m;

    [Fact]
    public void Throws_ArgumentException_if_position_is_zero()
    {
        Assert.Throws<ArgumentException>(() => number.DigitAtPosition(0));
    }

    [Fact]
    public void Throws_ArgumentException_if_position_is_negative()
    {
        Assert.Throws<ArgumentException>(() => number.DigitAtPosition(-5));
    }

    [Fact]
    public void Works_for_1st_digit()
    {
        Assert.Equal(3, number.DigitAtPosition(1));
    }

    [Fact]
    public void Works_for_28th_digit()
    {
        Assert.Equal(5, number.DigitAtPosition(28));
    }

    [Fact]
    public void Works_for_negative_decimals()
    {
        const decimal negativeNumber = -number;
        Assert.Equal(5, negativeNumber.DigitAtPosition(28));
    }

    [Fact]
    public void Returns_zero_for_whole_numbers()
    {
        const decimal wholeNumber = decimal.MaxValue;
        Assert.Equal(0, wholeNumber.DigitAtPosition(1));
    }

    [Fact]
    public void Returns_zero_if_position_is_greater_than_the_number_of_decimal_digits()
    {
        Assert.Equal(0, number.DigitAtPosition(29));
    }

    [Fact]
    public void Does_not_throw_if_number_is_max_decimal_value()
    {
        Assert.DoesNotThrow(() => decimal.MaxValue.DigitAtPosition(1));
    }

    [Fact]
    public void Does_not_throw_if_number_is_min_decimal_value()
    {
        Assert.DoesNotThrow(() => decimal.MinValue.DigitAtPosition(1));
    }

    [Fact]
    public void Does_not_throw_if_position_is_max_integer_value()
    {
        Assert.DoesNotThrow(() => number.DigitAtPosition(int.MaxValue));
    }
}

編輯:這里完全有錯誤和相反的答案。 我正在計算小數點左邊的位置而不是右邊的位置。 請參閱upvoted答案以獲取正確的代碼。

我發現這個工作在這里

public int ValueAtPosition(int value, int position)
{
    var result = value / (int)Math.Pow(10, position);
    result = result % 10;
    return result;
}

而這一個知道完整的價值(即:111,位置3 = 100,對不起,我不知道正確的名稱):

public int FullValueAtPosition(int value, int position)
{
    return this.ValueAtPosition(value, position) * (int)Math.Pow(10, position);
}

這個怎么樣:

protected static int FindNDigit(decimal value, int position)
{
    var index = value.ToString().IndexOf(".");
    position = position + index;
    return (int)Char.GetNumericValue(value.ToString(), position);
}

以前的解決方案都不適合我,所以這里有一個工作:

var result = value / Math.Pow(10, Math.Truncate((Math.Log10(value) + 1) - position)); return (int)(result % 10);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM