C# 从基数转换为十进制变得疯狂

C# Converting From Base to Decimal went Crazy

所以我想到了将任何基数转换为十进制(基数 10)的想法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SoloLearn
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("What is the number you want to convert?");
            string num = Console.ReadLine();
            Console.WriteLine("In what base is this number?");
            int mathBase = int.Parse(Console.ReadLine());
            double output = 0;
            int j = 0;
            char[] nums = num.ToCharArray();
            for(int i=num.Length - 1; i>=0; i--) {
               output = output + Math.Pow(mathBase,i) * nums[j] * 1;
               Console.WriteLine("i: " + i +", j:" + j + ", nums[j]: " + nums[j] + ", output: " + output + ", mathBase: " + mathBase + ", " + Math.Pow(mathBase,i) + ".");
               j++; 
            }
            Console.WriteLine("The number " + num + " in base 10 (Decimal) is " + output + ".");
            Console.ReadLine();
        }
    }
}

所以我从二进制 (num = 100, mathBase = 2) 开始,但答案太疯狂了。这就是为什么我添加此代码以查看到底发生了什么:

Console.WriteLine("i: " + i +", j:" + j + ", nums[j]: " + nums[j] + ", output: " + output + ", mathBase: " + mathBase + ", " + Math.Pow(mathBase,i) + "."); 
j++;  

嗯,所有变量都是正确的:

所以是的,我真的不知道发生了什么,因为所有的计算似乎都是正确的(Math.Pow(mathBase,i) = 2^2 = 4,如图所示,但是,4 * nums[j] = 4 * 1 = 196?如果有人知道到底发生了什么,请告诉我!

你的问题是 numschar[]。因此 nums[j] 是一个字符。现在您看到的问题是 char 可以隐式转换为数字,但不是您想要的方式 - 它使用它的 ascii 值,所以 1 是 ascii 值 49,0 是 ascii 值 48。那时候数学全错了。

您需要做的是将您的输入字符串转换为一个整数数组,而不是一个字符数组。可能执行此操作的一些示例代码是:

int[] nums = num.Select(x=>x-'0').ToArray();

这样做是利用字符 0-9 是 ascii 48-57 的事实,如果你从每个字符中取出 ascii 0 (48),你将得到 0-9。它还利用了字符串也是 IEnumerable<char> 的事实,因此可以轻松地进行 LINQ。

通过此修改,您的程序应该可以按预期运行。

这里的 num[j] 是一个字符,所以你应该在任何计算之前把它转换成 int。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SoloLearn
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("What is the number you want to convert?");
            string num = Console.ReadLine();
            Console.WriteLine("In what base is this number?");
            int mathBase = int.Parse(Console.ReadLine());
            double output = 0;
            int j = 0;
            char[] nums = num.ToCharArray();
            for(int i=num.Length - 1; i>=0; i--) {
               output = output + Math.Pow(mathBase,i) * Int32.Parse(nums[j].ToString()) * 1;
               Console.WriteLine("i: " + i +", j:" + j + ", nums[j]: " + nums[j] + ", output: " + output + ", mathBase: " + mathBase + ", " + Math.Pow(mathBase,i) + ".");
               j++; 
            }
            Console.WriteLine("The number " + num + " in base 10 (Decimal) is " + output + ".");
            Console.ReadLine();
        }
    }
}

任意基数转换时,您必须至少处理三个范围:

   '0'..'9' corresponds to  0..9
   'a'..'z' corresponds to 10..36
   'A'..'Z' corresponds to 10..36

所以你必须在你的代码中插入:

   for (int i=num.Length - 1; i>=0; i--) {
     // actual char, say 'C'
     int c = nums[j];
     // corresponding integer value, 12
     int v = 0;

     if (c >= '0' && c <= '9')
       v = c - '0';
     else if (c >= 'a' && c <= 'z')
       v = c - 'a' + 10; 
     else if (c >= 'A' && c <= 'Z')
       v = c - 'A' + 10; 

     // please, notice not nums[j] but the value it corresponds to - v
     output = output + Math.Pow(mathBase, i) * v;
     ...
   }

P.S。在 Linq 的帮助下,您可以简明扼要:

  string num = "abC02";
  int mathBase = 16;

  int result = num
    .Select(c =>
         c >= '0' && c <= '9' ? c - '0'
       : c >= 'a' && c <= 'z' ? c - 'a' + 10
       : c >= 'A' && c <= 'Z' ? c - 'A' + 10
       : 0)
    .Aggregate((s, a) => s * mathBase + a);

  // 703490
  Console.Write(result);