Изящно определите, “верна” ли больше чем одна булевская переменная

Предупреждение: Деление на ноль

Предупреждающее сообщение «Подразделение на ноль» является одним из наиболее часто задаваемых вопросов среди новых разработчиков PHP. Эта ошибка не вызовет исключения, поэтому некоторые разработчики будут иногда подавлять предупреждение, добавляя оператор подавления ошибок @ перед выражением. Например:

$value = @(2 / 0);

Но, как и при любом предупреждении, наилучшим подходом было бы отслеживать причину предупреждения и разрешать его. Причина предупреждения будет происходить из любого экземпляра, где вы пытаетесь разделить на 0, переменную, равную 0, или переменную, которая не была назначена (поскольку NULL == 0), потому что результат будет «неопределенным».

Чтобы исправить это предупреждение, вы должны переписать свое выражение, чтобы проверить, что значение не равно 0, если оно есть, сделать что-то еще. Если значение равно нулю, вы не должны делиться или изменять значение на 1, а затем делить так, что деление приводит к эквиваленту того, что он разделен только дополнительной переменной.

if ( $var1 == 0 ) { // check if var1 equals zero
    $var1 = 1; // var1 equaled zero so change var1 to equal one instead
    $var3 = ($var2 / $var1); // divide var1/var2 ie. 1/1
} else {
    $var3 = ($var2 / $var1); // if var1 does not equal zero, divide
}

Вопросы, относящиеся:

73
задан kay 2 June 2013 в 15:29
поделиться

19 ответов

Как насчет

  if ((bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + 
      (bool4? 1:0) + (bool5? 1:0) > 1)
      // do something

или обобщенный метод был бы...

   public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    {
       int trueCnt = 0;
       foreach(bool b in bools)
          if (b && (++trueCnt > threshold)) 
              return true;
       return false;          
    } 

или использующий LINQ, как предложено другими ответами:

    public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    { return bools.Count(b => b) > threshold; }

РЕДАКТИРОВАНИЕ (для добавления предложения Joel Coehoorn: (в.Net 2.x и позже)

    public void ExceedsThreshold<T>(int threshold, 
                      Action<T> action, T parameter, 
                      IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(parameter); }

или в.Net 3.5 и позже:

    public void ExceedsThreshold(int threshold, 
            Action action, IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(); }

или как расширение IEnumerable<bool>

  public static class IEnumerableExtensions
  {
      public static bool ExceedsThreshold<T> 
         (this IEnumerable<bool> bools, int threshold)
      { return bools.Count(b => b) > threshold; }
  }

использование тогда было бы:

  var bools = new [] {true, true, false, false, false, false, true};
  if (bools.ExceedsThreshold(3))
      // code to execute  ...
85
ответ дан ThdK 24 November 2019 в 12:06
поделиться

Вы упомянули

, Одна интересная опция состоит в том, чтобы сохранить булевские переменные в байте, сделать сдвиг вправо и соответствовать исходному байту. Что-то как if (myByte && (myByte >> 1))

я не думаю, что выражение даст Вам результат, который Вы хотите (по крайней мере, использующий C семантика, так как выражение не является допустимым C#):

, Если (myByte == 0x08), то выражение возвратит true даже при том, что существует только один набор битов.

, Если Вы имели в виду" if (myByte & (myByte >> 1))" тогда, если (myByte == 0x0a) выражение возвратит false даже при том, что существует набор на 2 бита.

, Но вот некоторые методы для подсчета числа битов, одним словом:

Взломы Битового жонглирования - подсчет битов

изменение А, которое Вы могли бы рассмотреть, должно использовать метод подсчета Kernighan, но прыгнуть с парашютом рано, так как только необходимо знать, существует ли больше чем один набор битов:

int moreThanOneBitSet( unsigned int v)
{
    unsigned int c; // c accumulates the total bits set in v

    for (c = 0; v && (c <= 1); c++)
    {
      v &= v - 1; // clear the least significant bit set
    }

    return (c > 1);
}

, Конечно, с помощью таблицы поиска не плохая опция также.

0
ответ дан Michael Burr 24 November 2019 в 12:06
поделиться

если ((b1. CompareTo (ложь) + b2. CompareTo (ложь) + b3. CompareTo (ложь) +...),> 1)

//больше чем один из них верен

...

еще

...

0
ответ дан Partha Choudhury 24 November 2019 в 12:06
поделиться

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

0x 0000 0000 
0x 0000 0001
0x 0000 0010
0x 0000 0100
0x 0000 1000
0x 0001 0000

Это дает Вам шесть значений, чтобы искать, поместить их в таблицу поиска и если это не там, у Вас есть свой ответ.

Это дает Вам простой ответ.

   public static boolean moreThan1BitSet(int b)
   {
      final short multiBitLookup[] = { 
            1, 1, 1, 0, 1, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0
      };
      if(multiBitLookup[b] == 1)
         return false;
      return true;
   }

Это не масштабирует хорошо прошлые 8 битов, но Вы только имеете пять.

0
ответ дан 24 November 2019 в 12:06
поделиться

На большинстве верных языков эквивалентно ненулевому значению, в то время как ложь является нулем. У меня нет точного синтаксиса для Вас, но в псевдо коде, что относительно:

if ((bool1 * 1) + (bool2 * 1) + (bool3 * 1) > 2)
{
    //statements here
}
0
ответ дан Bork Blatt 24 November 2019 в 12:06
поделиться

У меня есть намного намного лучший теперь и очень короткий!

bool[] bools = { b1, b2, b3, b4, b5 };
if (bools.Where(x => x).Count() > 1)
{
   //do stuff
}
1
ответ дан John Sonmez 24 November 2019 в 12:06
поделиться

Не точно довольно..., но вот другой способ сделать это:

if (
    (a && (b || c || d || e)) ||
    (b && (c || d || e)) ||
    (c && (d || e)) ||
    (d && e)
)
1
ответ дан Vilx- 24 November 2019 в 12:06
поделиться
if (NumberOfTrue(new List<bool> { bool1, bool2, bool3, bool4 }) >= 2)
{
    // do stuff
}

int NumberOfTrue(IEnumerable<bool> bools)
{
    return bools.Count(b => b);
}
1
ответ дан AndreasN 24 November 2019 в 12:06
поделиться

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

        public void YourFunction()
        {
            if(AtLeast2AreTrue(b1, b2, b3, b4, b5))
            {
                // do stuff
            }
        }

        private bool AtLeast2AreTrue(params bool[] values)
        {
            int trueCount = 0;
            for(int index = 0; index < values.Length || trueCount >= 2; index++)
            {
                if(values[index])
                    trueCount++;
            }

            return trueCount > 2;

        }
1
ответ дан John Sonmez 24 November 2019 в 12:06
поделиться

Бросок к ints и подведение итогов должны работать, но это немного ужасно, и на некоторых языках может не быть возможным.

Как насчет чего-то как

int count = (bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + (bool4? 1:0) + (bool5? 1:0);

Или если Вы не заботитесь о пространстве, Вы могли бы просто предварительно вычислить таблицу истинности и использовать bools в качестве индексов:

if (morethanone[bool1][bool2][bool3][bool4][bool5]) {
 ... do something ...
}
1
ответ дан frankodwyer 24 November 2019 в 12:06
поделиться

В то время как мне нравится LINQ, существуют некоторые дыры в нем, как эта проблема.

Проведение подсчета прекрасно в целом, но может стать проблемой, когда объекты Ваш подсчет требуют времени для вычисления/получения.

Любой () дополнительный метод прекрасен, если Вы просто хотите проверить на кого-либо, но если Вы хотите проверить на, по крайней мере, существует не создано в функции, которая сделает это и будет ленива.

В конце, я записал функцию для возвращения true, если существует, по крайней мере, определенное число объектов в списке.

public static bool AtLeast<T>(this IEnumerable<T> source, int number)
{
    if (source == null)
        throw new ArgumentNullException("source");

    int count = 0;
    using (IEnumerator<T> data = source.GetEnumerator())
        while (count < number && data.MoveNext())
        {
            count++;
        }
    return count == number;
}

Для использования:

var query = bools.Where(b => b).AtLeast(2);

Это обладает преимуществом не необходимости оценить все объекты прежде, чем возвратить результат.

[Разъем] Мой проект, NExtension содержит AtLeast, AtMost и переопределения, которые позволяют, Вы для смешивания в предикате с По крайней мере/Больше всего проверяете. [/Разъем]

2
ответ дан Cameron MacFarland 24 November 2019 в 12:06
поделиться

от вершины моей головы, быстрого подхода для этого определенного примера; Вы могли преобразовать bool в интервал (0 или 1). тогда цикл через терм и складывает их. если результат> = 2 тогда можно выполнить функцию.

2
ответ дан Bill the Lizard 24 November 2019 в 12:06
поделиться

если Вы имеете в виду больше чем или равный одной булевской переменной, равняется истинному, Вы могли бы сделать это как

if (bool1 || bool2 || bool3 || bool4 || bool5)

при необходимости в больше чем одном (2 и выше) булевские переменные, равные истинному можно попробовать

int counter = 0;
if (bool1) counter++;
if (bool2) counter++;
if (bool3) counter++;
if (bool4) counter++;
if (bool5) counter++;
if (counter >= 2) //More than 1 boolean is true
5
ответ дан Martin York 24 November 2019 в 12:06
поделиться

Короче и более ужасный, чем версия Vilx-s:

if (((a||b||c)&&(d||e))||((a||d)&&(b||c||e))||(b&&c)) {}
4
ответ дан some 24 November 2019 в 12:06
поделиться

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

Работают усерднее для прояснения, не умный!

private int CountTrues( params bool[] booleans )
{
    int result = 0;
    foreach ( bool b in booleans )
    {
        if ( b ) result++;
    }

    return result;
}
6
ответ дан rp. 24 November 2019 в 12:06
поделиться

Я просто бросил бы их к ints и сумме.

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

16
ответ дан recursive 24 November 2019 в 12:06
поделиться

Время для обязательного ответа LINQ, который в этом случае на самом деле довольно аккуратен.

var bools = new[] { true, true, false, false, false };

return bools.Count(b => b == true) > 1;
18
ответ дан Garry Shutler 24 November 2019 в 12:06
поделиться

Я собирался записать версию Linq, но приблизительно пять человек побеждают меня к ней. Но мне действительно нравится, когда подход параметрических усилителей избегает необходимости вручную новый массив. Таким образом, я думаю, что лучший гибрид, на основе ответа армированного пластика с заменой тела очевидным Linqness:

public static int Truth(params bool[] booleans)
{
    return booleans.Count(b => b);
}

Красиво ясный читать и использовать:

if (Truth(m, n, o, p, q) > 2)
115
ответ дан Daniel Earwicker 24 November 2019 в 12:06
поделиться

Если были миллионов вместо 5, вы можете избежать Count () и сделать это вместо этого ...

public static bool MoreThanOne (IEnumerable<bool> booleans)
{
    return booleans.SkipWhile(b => !b).Skip(1).Any(b => b);
}
5
ответ дан 24 November 2019 в 12:06
поделиться
Другие вопросы по тегам:

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