Как я проверяю, даже ли целое число или нечетно? [закрытый]

Чтобы избежать всех отрицательных эффектов инициализации двойной комбинации, например:

  1. Сломанная «равна» совместимости.
  2. При выполнении прямых назначений никаких проверок не выполнялось.
  3. Возможные утечки памяти.

делать следующие вещи:

  1. Сделать отдельный класс «Builder» особенно для инициализации двойной привязки.
  2. Объявить поля со значениями по умолчанию.
  3. Поместить метод создания объекта в этот класс.

Пример:

public class MyClass {
    public static class Builder {
        public int    first  = -1        ;
        public double second = Double.NaN;
        public String third  = null      ;

        public MyClass create() {
            return new MyClass(first, second, third);
        }
    }

    protected final int    first ;
    protected final double second;
    protected final String third ;

    protected MyClass(
        int    first ,
        double second,
        String third
    ) {
        this.first = first ;
        this.second= second;
        this.third = third ;
    }

    public int    first () { return first ; }
    public double second() { return second; }
    public String third () { return third ; }
}

Использование :

MyClass my = new MyClass.Builder(){{ first = 1; third = "3"; }}.create();

Преимущества:

  1. Просто использовать.
  2. Не разрывает совместимость «равно».
  3. Вы может выполнять проверки в методе создания.
  4. Отсутствует утечка памяти.

Недостатки:

  • Нет.

И, как результат, у нас самый простой шаблон java-строителя.

См. все образцы в github: java-sf-builder-simple-example

193
задан ruakh 23 February 2015 в 13:51
поделиться

20 ответов

Используйте по модулю (%) оператор, чтобы проверить, существует ли остаток при делении на 2:

if (x % 2) { /* x is odd */ }

Несколько человек подвергли критике мой ответ выше утверждения того использования x & 1 "быстрее" или "более эффективен". Я не полагаю, что это имеет место.

Из любопытства, я создал две тривиальных программы тестового сценария:

/* modulo.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x % 2)
            printf("%d is odd\n", x);
    return 0;
}

/* and.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x & 1)
            printf("%d is odd\n", x);
    return 0;
}

я тогда скомпилировал их с gcc 4.1.3 на одной из моих машин 5 различных раз:

  • Без флагов оптимизации.
  • С-O
  • С - OS
  • С-O2
  • С-O3

я исследовал вывод блока каждой компиляции (использующий gcc-S) и нашел, что в каждом случае, вывод для and.c и modulo.c был идентичен (они оба использовали andl 1$, %eax инструкция). Я сомневаюсь, что это - "новая" функция, и я подозреваю, что она относится ко времени древних версий. Я также сомневаюсь относительно любого современного (сделанный за прошлые 20 лет), нетайный компилятор, коммерческий или с открытым исходным кодом, испытывает недостаток в такой оптимизации. Я протестировал бы на других компиляторах, но я не имею никого в наличии в данный момент.

, Если бы кто-либо еще хотел бы протестировать другие компиляторы и/или цели платформы, и получает различный результат, мне очень было бы интересно знать.

Наконец, версия по модулю , гарантировал по стандарту, чтобы работать, положительно ли целое число, отрицательно или нуль, независимо от представления реализации целых чисел со знаком. Поразрядное - и версия не. Да, я понимаю, что дополнение two несколько повсеместно, таким образом, это не действительно проблема.

449
ответ дан Chris Young 23 November 2019 в 05:25
поделиться

Если Вы хотите быть эффективными, используйте побитовые операторы (x & 1), но если Вы хотите быть читаемым использованием по модулю 2 (x % 2)

0
ответ дан Vihung 23 November 2019 в 05:25
поделиться

Ради обсуждения...

только необходимо посмотреть на последнюю цифру в любом данном числе, чтобы видеть, даже ли это или нечетно. Со знаком, неподписанный, положительный, отрицательный - они являются всеми одинаковыми относительно этого. Таким образом, это должно работать повсюду вокруг: -

void tellMeIfItIsAnOddNumberPlease(int iToTest){
  int iLastDigit;
  iLastDigit = iToTest - (iToTest / 10 * 10);
  if (iLastDigit % 2 == 0){
    printf("The number %d is even!\n", iToTest);
  } else {
    printf("The number %d is odd!\n", iToTest);
  }
}

ключ здесь находится в третьей строке кода, оператор деления выполняет целочисленное деление, так, чтобы результат пропустил дробную часть результата. Так, например, 222 / 10 даст 22 в результате. Тогда умножьте его снова с 10, и Вы имеете 220. Вычтите это из оригинала 222, и Вы заканчиваете с 2, который волшебством является тем же числом как последняя цифра в исходном числе.;-) круглая скобка там для напоминания нам о порядке, в вычислении выполняют. Сначала сделайте разделение и умножение, затем вычтите результат исходного числа. Мы могли пропустить их, так как приоритет выше для разделения и умножения, чем вычитания, но это дает нам "больше читаемого" кода.

Мы могли сделать все это абсолютно нечитабельным, если бы мы хотели. Это не имело бы никакого значения вообще для современного компилятора: -

printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");

, Но это сделало бы код путем тяжелее для поддержания в будущем. Просто предположите, что требуется измениться, текст для нечетных чисел к "даже не". Тогда кто-то еще позже хочет узнать то, что изменяет Вас сделанный, и выполните svn разность или подобный...

, Если Вы не волнуетесь по поводу мобильности, но больше по поводу скорости, Вы могли бы взглянуть на наименее значимый бит. Если тот бит установлен на 1, это - нечетное число, если это 0, это - четное число. В небольшой системе порядка байтов как x86 архитектура Intel это было бы что-то вроде этого: -

if (iToTest & 1) {
  // Even
} else {
  // Odd
}
0
ответ дан Tooony 23 November 2019 в 05:25
поделиться
int isOdd(int i){
  return(i % 2);
}

сделанный.

1
ответ дан None 23 November 2019 в 05:25
поделиться

Портативный:

i % 2 ? odd : even;

Непортативный:

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;
2
ответ дан ilitirit 23 November 2019 в 05:25
поделиться

IsOdd (интервал x) {возвращают true;}

Доказательство правильности - рассматривает набор всех положительных целых чисел и предполагает, что существует непустое множество целых чисел, которые не нечетны. Поскольку положительные целые числа упорядочены, будет самое маленькое не нечетное число, которое сам по себе довольно нечетно, настолько ясно, что число не может быть в наборе. Поэтому этот набор не может быть непустым. Повторитесь для отрицательных целых чисел кроме, ищут самое большое не нечетное число.

2
ответ дан plinth 23 November 2019 в 05:25
поделиться

Поразрядный метод зависит от внутреннего представления целого числа. По модулю будет работать где угодно существует оператор по модулю. Например, некоторые системы на самом деле используют низкоуровневые биты для меток (как динамические языки), таким образом, сырые данные x & 1 не будет на самом деле работать в этом случае.

2
ответ дан Will Hartung 23 November 2019 в 05:25
поделиться

В "творческой, но запутывающей категории" я предлагаю:

int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }

вариант А на этой теме, которая характерна для Microsoft C ++:

__declspec(naked) bool __fastcall isOdd(const int x)
{
    __asm
    {
        mov eax,ecx
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        ret
    }
}
3
ответ дан DocMax 23 November 2019 в 05:25
поделиться

Я знаю, что это - просто синтаксический сахар и только применимый в .net, но что относительно дополнительного метода...

public static class RudiGroblerExtensions
{
    public static bool IsOdd(this int i)
    {
        return ((i % 2) != 0);
    }
}

Теперь можно сделать следующий

int i = 5;
if (i.IsOdd())
{
    // Do something...
}
3
ответ дан rudigrobler 23 November 2019 в 05:25
поделиться
i % 2 == 0
8
ответ дан Mark Cidade 23 November 2019 в 05:25
поделиться
// C#
bool isEven = ((i % 2) == 0);
5
ответ дан Michael Petrotta 23 November 2019 в 05:25
поделиться

Еще одно решение проблемы
(дети могут голосовать)

bool isEven(unsigned int x)
{
  unsigned int half1 = 0, half2 = 0;
  while (x)
  {
     if (x) { half1++; x--; }
     if (x) { half2++; x--; }

  }
  return half1 == half2;
}
6
ответ дан eugensk 23 November 2019 в 05:25
поделиться

Я сказал бы, просто делят его на 2 и если существует 0 остатков, это даже, иначе это нечетно.

Используя модуль (%) делает это легким.

, например, 4% 2 = 0 поэтому 4 даже 5% 2 = 1 поэтому 5, нечетен

7
ответ дан Jarod Elliott 23 November 2019 в 05:25
поделиться

Число - то, даже если, когда разделено на два, остаток 0. Число нечетно, если, когда разделено на 2, остаток равняется 1.

// Java
public static boolean isOdd(int num){
    return num % 2 != 0;
}

/* C */
int isOdd(int num){
    return num % 2;
}

Методы являются замечательными!

11
ответ дан jjnguy 23 November 2019 в 05:25
поделиться

Хороший:

/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);

bool isEven(unsigned int n)
{
  if (n == 0) 
    return true ;  // I know 0 is even
  else
    return isOdd(n-1) ; // n is even if n-1 is odd
}

bool isOdd(unsigned int n)
{
  if (n == 0)
    return false ;
  else
    return isEven(n-1) ; // n is odd if n-1 is even
}

Примечание, что эта хвостовая рекурсия использования метода, включающая две функции. Это может быть реализовано эффективно (превратился, в то время как/до вид цикла), если Ваш компилятор поддерживает хвостовую рекурсию как компилятор Схемы. В этом случае стек не должен переполняться!

14
ответ дан fortran 23 November 2019 в 05:25
поделиться

В ответ на ffpf - у меня был точно тот же спор с коллегой несколько лет назад, и ответ никакой , это не работает с отрицательными числами.

стандарт C предусматривает, что отрицательные числа могут быть представлены 3 способами:

  • 2's дополнение
  • 1's дополнение
  • знак и магнитуда

, Проверяющая как это:

isEven = (x & 1);

будет работать на 2's дополнение и подписываться и представление величины, но не для 1's дополнение.

Однако я полагаю, что следующее будет работать на все случаи:

isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));

<глоток> Благодаря ffpf для указания, что текстовое поле ело все после моих меньше, чем символ!

16
ответ дан Community 23 November 2019 в 05:25
поделиться

[Режим Joke = "на"]

public enum Evenness
{
  Unknown = 0,
  Even = 1,
  Odd = 2
}

public static Evenness AnalyzeEvenness(object o)
{

  if (o == null)
    return Evenness.Unknown;

  string foo = o.ToString();

  if (String.IsNullOrEmpty(foo))
    return Evenness.Unknown;

  char bar = foo[foo.Length - 1];

  switch (bar)
  {
     case '0':
     case '2':
     case '4':
     case '6':
     case '8':
       return Evenness.Even;
     case '1':
     case '3':
     case '5':
     case '7':
     case '9':
       return Evenness.Odd;
     default:
       return Evenness.Unknown;
  }
}

[Режим Joke = "прочь"]

РЕДАКТИРОВАНИЕ: Добавленные запутывающие значения к перечислению.

36
ответ дан Sklivvz 23 November 2019 в 05:25
поделиться

Использование укусило арифметику:

if((x & 1) == 0)
    printf("EVEN!\n");
else
    printf("ODD!\n");

Это быстрее, чем использование подразделения или модуля.

97
ответ дан Adam Pierce 23 November 2019 в 05:25
поделиться

Вы парни waaaaaaaay слишком эффективный. То, что Вы действительно хотите:

public boolean isOdd(int num) {
  int i = 0;
  boolean odd = false;

  while (i != num) {
    odd = !odd;
    i = i + 1;
  }

  return odd;
}

Повторение для isEven.

, Конечно, который не работает на отрицательные числа. Но с блеском прибывает жертва...

208
ответ дан brimborium 23 November 2019 в 05:25
поделиться

Я бы построил таблицу четностей (0, если даже 1, если нечетное) целых чисел (чтобы можно было сделать поиск: D), но gcc не позволяет мне создавать массивы таких размеров:

typedef unsigned int uint;

char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;

void build_parity_tables () {
    char parity = 0;
    unsigned int ui;
    for (ui = 1; ui <= UINT_MAX; ++ui) {
        parity_uint [ui - 1] = parity;
        parity = !parity;
    }
    parity = 0;
    int si;
    for (si = 1; si <= INT_MAX; ++si) {
        parity_sint [si - 1] = parity;
        parity = !parity;
    }
    parity = 1;
    for (si = -1; si >= INT_MIN; --si) {
        parity_sint [si] = parity;
        parity = !parity;
    }
}

char uparity (unsigned int n) {
    if (n == 0) {
        return 0;
    }
    return parity_uint [n - 1];
}

char sparity (int n) {
    if (n == 0) {
        return 0;
    }
    if (n < 0) {
        ++n;
    }
    return parity_sint [n - 1];
}

Так что давайте вместо этого прибегнем к математическому определению четного и нечетного.

Целое число n есть даже в том случае, если существует такое целое число k, что n = 2k.

Целое число n является нечетным, если существует целое число k такое, что n = 2k + 1.

Вот его код:

char even (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k) {
            return 1;
        }
    }
    return 0;
}

char odd (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k + 1) {
            return 1;
        }
    }
    return 0;
}

Пусть C-целые числа обозначают возможные значения int в данной компиляции C. (Обратите внимание, что C-целые числа - это подмножество целых чисел.)

Теперь можно беспокоиться, что для данного n в C-целых числах соответствующее целое число k может не существовать в C-целых числах. Но с небольшим доказательством можно показать, что для всех целых n, | n | <= | 2n | (*), где | n | равно "n, если n положительно, и -n в противном случае". Другими словами, для всех n в целых числах выполняется хотя бы одно из следующего (на самом деле, либо случаи (1 и 2), либо случаи (3 и 4), но я не буду это здесь доказывать):

Случай 1: п <= 2n.

Случай 2: -n <= -2n.

Случай 3: -n <= 2n.

Случай 4: n <= -2n.

Теперь возьмем 2k = n. (Такой ak действительно существует, если n четно, но я не буду здесь это доказывать. Если n не четное, то цикл в даже все равно не возвращается раньше, поэтому это не имеет значения.) это означает, что k даже , следовательно k = 0 находится в C-целых числах). Таким образом, такое k в C-целых числах существует для n в C-целых числах, если n четно.

Аналогичное рассуждение показывает, что если n нечетно, существует ak в C-целых числах такое, что n = 2k + 1.

Следовательно, функции четные и нечетные представлены здесь будет работать правильно для всех C-целых чисел.

6
ответ дан 23 November 2019 в 05:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: