【问题标题】:C# Decimal To OctalC# 十进制转八进制
【发布时间】:2018-01-26 05:55:04
【问题描述】:

有很多问题,但我似乎无法在答案中找到原因。通常是:不,用这个替换它,否则它应该可以工作。

我的任务是创建一个程序,要求用户输入一个 3 位正整数(十进制),然后将其转换为八进制。

例如,在纸上:将数字 112 转换为八进制。 (8 是八进制的基数。)

这些是您将采取的步骤:

  • 112 / 8 = 14 余数 = 0
  • 14 / 8 = 1 余数 = 6
  • 1 / 8 = 0 余数 = 1

余数从下到上是八进制数,十进制表示 112。 所以 112 的八进制数是 160。

我在互联网上找到了以下程序,但我不完全理解。 程序中的cmets是我的。谁能给我解释一下?

        //declaration and initialization of variables but why is there an array?
        int decimalNumber, quotient, i = 1, j;
        int[] octalNumber = new int[100];

        //input
        Console.WriteLine("Enter a Decimal Number :");
        decimalNumber = int.Parse(Console.ReadLine());

        quotient = decimalNumber;

        //as long as quotient is not equal to 0, statement will run
        while (quotient != 0)
        {
            //this is how the remainder is calculated but it is then put in an array + 1, i don't understand this.
            octalNumber[i++] = quotient % 8;
            //divide the number given by the user with the octal base number
            quotient = quotient / 8;
        }
        Console.Write("Equivalent Octal Number is ");
        //i don't understand the code below here aswell. 
        for (j = i - 1; j > 0; j--)
            Console.Write(octalNumber[j]);
        Console.Read();

非常感谢任何帮助。

【问题讨论】:

  • Convert.ToString(decimalNumber, 8)不够好吗?
  • 有一个数组,因为每个八进制数字都存储在一个位置。最后,存储在数组中的数字以相反的顺序写入控制台。

标签: c# decimal octal


【解决方案1】:

首先要理解的是:这是解决这个问题的糟糕方法。 代码中充满了奇怪的选择;看起来有人对这个问题采用了一个糟糕的 C 解决方案并将其转换为 C#,而没有经过仔细考虑或使用良好的实践。如果您正在尝试学习如何理解您在互联网上找到的蹩脚代码,这是一个很好的例子。如果您正在尝试学习如何设计好的代码,这是一个很好的例子,说明不该做什么。

//declaration and initialization of variables but why is there an array?

有一个数组是因为我们希望存储所有的八进制数字,而数组是一种方便的机制来存储许多相同类型的数据。

但我们可以在这里问一些更相关的问题:

  • 为什么是 100 号?这没有错,但这比必要的要大得多。什么样的思考过程导致 100 人被选中?为什么没有在任何地方记录这个思维过程?
  • 为什么是 int 数组?我们正在输出文本,这是一个字符序列。有一堆字符似乎更自然。
  • 为什么是数组?由于我们正在构建先进后出的数据结构,因此堆栈似乎更合适。或者为什么不简单地积累一个字符串?如果字符串很大,效率会很低,但是 32 位整数的八进制字符串永远不会很大!
  • 为什么程序会向控制台输出输出?当然,一个更好的因式分解程序应该有一个方法,它接受一个 int 并返回一个八进制字符串,然后可以打印出来。
  • 为什么有些变量具有描述性名称而有些具有非描述性名称?代码的作者是否故意混淆读者?还是他们根本没有仔细考虑?
  • 为什么i——显然是数组的当前索引——从一开始?!这简直太奇怪了。在 C# 中,数组从零开始。
  • 如果您输入负数会怎样?试试看!
  • 如果输入零会怎样?

然后我们继续:

decimalNumber = int.Parse(Console.ReadLine());

此代码假定输入的文本是合法的整数,这是不保证的。所以这个程序可能会崩溃。应使用TryParse,并处理故障模式。

 // this is how the remainder is calculated but it is 
 // then put in an array + 1, i don't understand this.
 octalNumber[i++] = quotient % 8;

代码的作者认为他们很聪明。这也太聪明了。将您脑海中的代码重写为最初应该如何实现。首先,将i 重命名为currentIndex。接下来,每个语句产生一个副作用,而不是两个

    while (quotient != 0)
    {
        octalNumber[currentIndex] = quotient % 8;
        currentIndex += 1;
        quotient = quotient / 8;
    }

现在应该清楚发生了什么。

 // I don't understand the code below here as well. 
 for (j = i - 1; j > 0; j--)
   Console.Write(octalNumber[j]);

做一个小例子。假设数字是 14,也就是八进制的 16。第一次通过循环,我们将 6 放入插槽 1。下一次,我们将 1 放入插槽 2。所以数组是 {0, 6, 1, 0, 0, 0, 0 ... }i 是 3。我们希望输出 16。所以我们将 j 从 i-1 循环到 1,然后打印出 1 然后 6。

所以,为你练习:再次编写这个程序,这次使用精心设计的 C# 程序的约定。将您的尝试放在代码审查网站上,人们会很乐意为您提供改进建议。

【讨论】:

  • “每条语句产生一个副作用”。你不是说“不产生副作用”吗,因为它实际上是一种效果而不是副作用,因为它是你想要的?请不要恨我! ;-)
  • 好点。如果它是预期的效果,它不是副作用!
  • 我一直认为数组中存储的数据是按时间顺序排列的。就像上面的例子一样:{0, 1, 6, 0, 0, .. }。并感谢您的精彩解释。这完全有道理。
  • @IliasJoels:数组只是一个设备,它采用 index 并根据需要生成与该索引对应的 variable。所以new int[100] 产生了一个包含 10 个变量的集合,索引从 0 到 9。
  • @EricLippert 我认为您的句子中有错字。但是朋友之间的数量级是多少? ;)
【解决方案2】:

这已经内置在 .NET 中,Convert.ToString 已经这样做了。

在您的代码中,在您拥有decimalNumber = int.Parse(...) 之后,您可以这样做:

Console.WriteLine(Convert.ToString(decimalNumber, 8));
Console.Read();

然后删除其余代码。

现在,如果您不是询问如何在 .NET 中进行八进制转换,而是询问该代码的实际工作原理,那么它是如何工作的:

这个循环完成了繁重的工作:

1   while (quotient != 0)
    {
        //this is how the remainder is calculated but it is then put in an array + 1, i don't understand this.
2       octalNumber[i++] = quotient % 8;
        //divide the number given by the user with the octal base number
3       quotient = quotient / 8;
    }

我在行中添加了一些数字,以便于编写描述。

基本上,循环就是这样做的(上面的行对应下面的点)。

  1. 只要我们有一个数字要转换(即,我们还没有完成),循环。
  2. 找出最低位,这是除以8后的余数,由remainder operator%处理,将此位存入数组中的下一个位置。
  3. 除以 8 以去除最低有效数字并将所有其他数字上移一位

然后循环回来。

但是,由于我们基本上找到了从最右侧到左侧的所有数字,因此最后的循环以相反的顺序将它们写回。

作为给读者的一个练习,尝试找出问题中的代码在以下情况下的行为:

  • 输入一个负数
  • 输入 0

(提示,它的行为不正确,但 Convert.ToString 可以)

【讨论】:

  • My task...部分帖子:)
  • 这样就省去了一半的代码。这更容易阅读,更容易理解。我不明白为什么程序员可以用 1 行来完成程序却让程序如此复杂。不,我只是在练习;)
  • @OrkhanAlikhanov 使用Convert.ToString 可以完美解决该任务,如果任务是“我必须自己编写所有代码作为家庭作业的一部分”,那么这是一个不同的问题。
  • 我注意到% 是余数运算符,而不是模数运算符。
  • 哦,相信我,我已经向文档团队表达了他们愿意在 C# 文档中多次编造疯狂的东西的强烈意见。
【解决方案3】:

使用数组是因为它们在 while 循环的每次交互中计算每个数字。 (例如){0, 6, 1}

程序的最后一部分是打印每个数字,从数组中的最后一项开始,移动到第一项。在这种情况下,它会打印出: 160

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 2015-12-12
    • 2011-08-21
    相关资源
    最近更新 更多