确定数字是十的倍数还是在一组特定范围内

use*_*168 104 c++ comparison conditional-statements integer-arithmetic

我的程序中需要一些循环.我可以写出伪代码,但我不完全确定如何逻辑地编写它们.

我需要 -

if (num is a multiple of 10) { do this }

if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90
Run Code Online (Sandbox Code Playgroud)

这是一个蛇和梯子棋盘游戏,如果它对我的问题更有意义.

我想第一个if语句我需要使用模数,是否if (num == 100%10)正确?

第二个我不知道.我可以写出来,if (num > 10 && num is < 21 || etc)但必须有比这更聪明的东西.

Win*_*ert 86

对于第一个,检查一个数字是否是使用的倍数:

if (num % 10 == 0) // its divisible by 10
Run Code Online (Sandbox Code Playgroud)

对于第二个:

if(((num - 1) / 10) % 2 == 1 && num <= 100)
Run Code Online (Sandbox Code Playgroud)

但这相当密集,你可能最好只是明确地列出选项.


既然你已经更好地了解了自己在做什么,我会把第二个写成:

   int getRow(int num) {
      return (num - 1) / 10;   
   }

   if (getRow(num) % 2 == 0) {
   }
Run Code Online (Sandbox Code Playgroud)

它的逻辑相同,但通过使用该功能,我们可以更清楚地了解它的含义.

  • `if((num - 1)/ 10)%2 == 1 && num <100)` - 如果我看到了,我会哭的. (79认同)
  • @DanielKamilKozar,你应该这样做. (32认同)
  • 断言`num> = 11`可能是谨慎的,因为(1)下限是被禁止的,而(2)负数上的'%`也返回负数.(我必须承认在这里使用"&1"是"更安全",但也承担了额外的知识.) (3认同)
  • @ user3419168,它本身就让人想知道这意味着什么.它没有提供关于它试图做什么的世界的暗示.这就是为什么在编辑中我展示了一个版本,它将逻辑分成一个函数,使得计算实际上更清楚. (2认同)
  • 编辑的+1,它进入范围列表的原因并以可读的方式呈现.IMO,一步就是将`getRow(num)%2 == 0`包装在一个函数中,以使其清晰明白意图是什么.`bool inEvenRow(int num){return getRow(num)%2 == 0;}` (2认同)
  • @ user3419168:在某些准则中,据说应该避免使用聪明的代码,尽管它很聪明,因为它很聪明。想一想一些数学上的构造,这些构造很聪明,但是并不明显。在编程中,当涉及更改和修正时,显而易见性值得很多钱。 (2认同)

Ada*_*iss 40

if(num是10的倍数){执行此操作}

if (num % 10 == 0) {
  // Do something
}
Run Code Online (Sandbox Code Playgroud)

if(num在11-20,31-40,51-60,71-80,91-100之间){执行此操作}

这里的诀窍是寻找范围之间的某种共性.当然,你总是可以使用"强力"方法:

if ((num > 10 && num <= 20) ||
    (num > 30 && num <= 40) ||
    (num > 50 && num <= 60) ||
    (num > 70 && num <= 80) ||
    (num > 90 && num <= 100)) {
  // Do something
}
Run Code Online (Sandbox Code Playgroud)

但是,你可能会注意到,如果你减去1num,你就会有范围:

10-19, 30-39, 50-59, 70-79, 90-99
Run Code Online (Sandbox Code Playgroud)

换句话说,所有2位数字的第一个数字是奇数.接下来,您需要提出一个表达这一点的公式.您可以通过除以10获得第一个数字,并且可以通过在除以2时检查余数为1来测试它是奇数.将它们全部放在一起:

if ((num > 0) && (num <= 100) && (((num - 1) / 10) % 2 == 1)) {
  // Do something
}
Run Code Online (Sandbox Code Playgroud)

考虑到更长但可维护的代码和更短的"聪明"代码之间的权衡,我每次都会选择更长更清晰的代码.至少,如果你想要聪明,请包括一个评论,准确解释你想要完成的事情.

它有助于假设下一个开发代码的开发人员已经武装起来并知道你住在哪里.:-)

  • 我仍然会寻找聪明的代码,但通过提取函数将其转换为可维护的代码.如果最后一位说`&& isTensDigitOdd(num)`,或者在函数定义之前用注释解释它的作用,它就是可读的.如果存在这样的模式,则解释该模式的推理的注释对于可维护性imo是有启发性的. (7认同)
  • 克里斯,当"聪明"具有明显优势时,这是一个很好的策略:更短的代码(这意味着错误的机会更少,特别是如果它发生变化),或效率的大幅提升.在简洁性,清晰度和效率之间几乎总是需要权衡,找到一个好的折衷方案是一项很好的开发技巧.(有关窃笑,请参见http://stackoverflow.com/a/2151844/29157.) (3认同)

Bry*_*hen 30

如果您使用的是GCC或任何支持Case Ranges的编译器,您可以执行此操作,但您的代码将无法移植

switch(num)
{
case 11 ... 20:
case 31 ... 40:
case 51 ... 60:
case 71 ... 80:
case 91 ... 100:
    // do something
    break;
default:
    // do something else
    break;
}
Run Code Online (Sandbox Code Playgroud)

  • @MSharathHegde因为它需要GCC扩展,这不是标准的一部分,有些编译器不支持它 (8认同)
  • 这是正确的答案,因为它的意图很明显.所有那些带有模数的"聪明"答案都是维护噩梦,即使有评论也是如此. (5认同)

chr*_*ris 15

这对未来的访客来说比初学者更多.对于更通用的类似算法的解决方案,您可以获取起始值和结束值的列表,并检查传递的值是否在其中一个内:

template<typename It, typename Elem>
bool in_any_interval(It first, It last, const Elem &val) {
    return std::any_of(first, last, [&val](const auto &p) {
        return p.first <= val && val <= p.second;
    });
}
Run Code Online (Sandbox Code Playgroud)

为简单起见,我使用了多态lambda(C++ 14)而不是显式pair参数.这也应该坚持使用<==与标准算法保持一致,但只要为Elem<=定义,它就像这样工作.无论如何,它可以像这样使用:

std::pair<int, int> intervals[]{
    {11, 20}, {31, 40}, {51, 60}, {71, 80}, {91, 100}
};

const int num = 15;
std::cout << in_any_interval(std::begin(intervals), std::end(intervals), num);
Run Code Online (Sandbox Code Playgroud)

有一个活生生的例子在这里.


小智 5

第一个很简单,你只需要将模数运算符应用于你的num值:

if ( ( num % 10 ) == 0)
Run Code Online (Sandbox Code Playgroud)

SInce c ++正在评估每个不为0的数字,你也可以写:

if ( ! ( num % 10 ) )  //does not have a residue when devided by 10
Run Code Online (Sandbox Code Playgroud)

对于第二个,我认为这更清楚:

模式每20次重复一次,因此您可以计算模20.除了可以被20分割的元素之外,您想要的所有元素都将排成一行.

要获得这些,只需使用num-1或更好的num + 19来避免处理负数.

if ( ( ( num + 19 ) % 20 ) > 9 )
Run Code Online (Sandbox Code Playgroud)

这假设模式永远重复,因此对于111-120,它将再次应用,依此类推.否则,您需要将数字限制为100:

if ( ( ( ( num + 19 ) % 20 ) > 9 ) && ( num <= 100 ) )
Run Code Online (Sandbox Code Playgroud)


La-*_*eja 5

在代码中有一些好的注释,它可以写得非常简洁和可读.

// Check if it's a multiple of 10
if (num % 10 == 0) { ... }

// Check for whether tens digit is zero or even (1-10, 21-30, ...)
if ((num / 10) % 2 == 0) { ... }
else { ... }
Run Code Online (Sandbox Code Playgroud)

  • 是的,但初学者也读了这个网站.我通常不会在我自己的代码中使用该注释,但它确实使初学者能够从这个初学者问题中获益更清楚. (7认同)
  • 第一条评论是不必要的.任何有一点经验的程序员都会知道`num%10 == 0`与`num`是10的倍数是一回事. (2认同)
  • 请不要这样做.它实际上降低了可读性,通过减慢读取器的速度并强制它们读取所有内容两次.任何不理解`if(num%10 == 0)`与`//检查它是否为10的倍数'的程序员不应该维护_your_代码.这是一个众所周知的反模式. (2认同)
  • 不,我的意思是对每一行进行注释来说明它的作用是一种反模式。我并不是说使用“%”是一种反模式;显然不是。实际上,假设这篇文章的许多读者都是初学者,教他们这种编写注释的风格会对他们作为程序员的发展产生负面影响。 (2认同)