【问题标题】:How can I extract the places values of a number?如何提取数字的位置值?
【发布时间】:2018-06-01 02:37:25
【问题描述】:

我正在使用 C# 在 Unity 游戏引擎中开发一个数学游戏,特别是一个可重用组件,用于教授乘法的网格方法。例如,当给定数字 34 和 13 时,它应该生成一个 3X3 网格(标题列和行用于乘数和被乘数位置值,2X2 用于乘数和被乘数中的位置数)。看起来像这样的东西:

我的问题是我不知道提取数字位置值的最佳方法(例如 34 -> 30 和 4)。我正在考虑将其转换为字符串,根据其索引将 0 添加到较高位置的值,然后将其转换回 int,但这似乎是一个糟糕的解决方案。有更好的方法吗?

注意:我几乎只处理正整数,但位值的数量可能会有所不同。


感谢所有回答的人!认为发布我使用所有回复构建的特定于 Unity 的解决方案可能会有所帮助:

List<int> GetPlaceValues(int num) {
    List<int> placeValues = new List<int>();
    while (num > 0) {
        placeValues.Add(num % 10);
        num /= 10;
    }
    for(int i = 0;i<placeValues.Count;i++) {
        placeValues[i] *= (int)Mathf.Pow(10, i);
    }
    placeValues.Reverse();
    return placeValues;
}

【问题讨论】:

  • 为什么不能使用字符串插值?为什么输出必须是数字?
  • @Greg 就组件而言,我最终需要使用数字来计算网格的其他部分(300,40,90,12)。
  • % 运算符呢?
  • 想想你在做什么,把代码变成现实。我们的数值系统具有位值不是很好吗?您可以从小数点读取任何单个数字和零索引,然后将该数字乘以 10 到该索引的幂?
  • @DavidRodriguez 我已经修改了我之前的答案,以便按照您的要求实际生成一个网格;这个花了一点时间!在您最终不得不这样做之前,这是您希望轻松完成的事情之一。

标签: c# unity3d math multiplication


【解决方案1】:

我的答案非常粗略,可能会被数学能力更好的人改进:

void Main()
{
    GetMulGrid(34, 13).Dump();
}

int[,] GetMulGrid(int x, int y)
{
    int[] GetPlaceValues(int num)
    {
        var numDigits = (int)Math.Floor(Math.Log10(num) + 1);
        var digits = num.ToString().ToCharArray().Select(ch => Convert.ToInt32(ch.ToString())).ToArray();
        var multiplied =
            digits
            .Select((d, i) =>
            {
                if (i != (numDigits - 1) && d == 0) d = 1;
                return d * (int)Math.Pow(10, (numDigits - i) - 1);
            })
            .ToArray();
        return multiplied;
    }

    var xComponents = GetPlaceValues(x);
    var yComponents = GetPlaceValues(y);

    var arr = new int[xComponents.Length + 1, yComponents.Length + 1];

    for(var row = 0; row < yComponents.Length; row++)
    {
        for(var col = 0; col < xComponents.Length; col++)
        {
            arr[row + 1,col + 1] = xComponents[col] * yComponents[row];
            if (row == 0)
            {
                arr[0, col + 1] = xComponents[col];
            }
            if (col == 0)
            {
                arr[row + 1, 0] = yComponents[row];
            }
        }
    }

    return arr;
}

对于您的 34 x 13 示例,它会产生:

对于 304 x 132,它会产生:

它将它作为一个数组输出,因此您如何使用和显示结果将取决于您。

【讨论】:

  • 哇,你已经超越了。我只是在寻找一种提取位置值的方法。 +1 努力!
【解决方案2】:

也许你想要这样的东西 (ideone):

int n = 76302;
int mul = 1;
int cnt = 0;
int res[10];

while(n) {
   res[cnt++] = (n % 10) * mul;
   mul*=10;
   cout << res[cnt-1] << " ";
   n = n / 10;
}

output 
2 0 300 6000 70000 

【讨论】:

    【解决方案3】:

    利用我们数字系统的工作方式。这是一个基本示例:

    string test = "12034";
    for (int i = 0; i < test.Length; ++i) {
        int digit = test[test.Length - i - 1] - '0';
        digit *= (int)Math.Pow(10, i);
        Console.WriteLine("digit = " + digit);
    }
    

    基本上,它从最右边的数字开始读取(假设输入是整数),并使用我们系统工作方式的方便位值来计算数字的含义。

    test.Length - i - 1 将最右侧视为 0,并在左侧索引为正数。

    - '0' 将“0”的编码值转换为实际数字。

    Play with the code

    【讨论】:

    • 被接受为答案,因为它最接近我正在寻找的东西。我使用模数来保持数字。
    • @DavidRodriguez 确实,Math.Pow 的东西帮助我获得了正确零的数字。
    【解决方案4】:

    对于两位数,您可以使用模数

    int n = 34;
    int x = n % 10;   // 4
    int y = n - x;    // 30
    

    【讨论】:

    • 使用模数绝对是最干净的解决方案。但我需要它来处理不同数量的位值,而不仅仅是两位数。我会尝试做一个循环,每次都改变模数。
    • 这里有个通用的解决方案,我还没想出来。
    猜你喜欢
    • 2020-07-27
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 2022-07-05
    • 2014-08-05
    相关资源
    最近更新 更多