Действительно ли приемлемо 'еще' только использовать часть 'если еще' оператор?

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

Что касается точного представления, Вы правы быть осторожными, потому что точная десятичная дробь как 1/10 не имеет никакого точного двоичного дубликата. Однако, если Вы знаете, что Вам только нужны 5 десятичных цифр точности, можно использовать , масштабировался арифметика, в которой Вы воздействуете на числа, умноженные на 10^5. Так, например, если Вы хотите представить 23.7205 точно, Вы представляете его как 2372050.

Позволяют нам видеть, существует ли достаточно точности: двойная точность дает Вам 53 бита точности. Это эквивалентно 15 + десятичные цифры точности. Таким образом, это позволило бы Вам пять цифр после десятичной точки и 10 цифр перед десятичной точкой, которая кажется вполне достаточной для Вашего приложения.

я поместил бы этот код C в.h файл:

typedef double scaled_int;

#define SCALE_FACTOR 1.0e5  /* number of digits needed after decimal point */

static inline scaled_int adds(scaled_int x, scaled_int y) { return x + y; }
static inline scaled_int muls(scaled_int x, scaled_int y) { return x * y / SCALE_FACTOR; }

static inline scaled_int scaled_of_int(int x) { return (scaled_int) x * SCALE_FACTOR; }
static inline int intpart_of_scaled(scaled_int x) { return floor(x / SCALE_FACTOR); }
static inline int fraction_of_scaled(scaled_int x) { return x - SCALE_FACTOR * intpart_of_scaled(x); }

void fprint_scaled(FILE *out, scaled_int x) {
  fprintf(out, "%d.%05d", intpart_of_scaled(x), fraction_of_scaled(x));
}

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

Никакие издержки для дополнения, стоимости умножения или делятся, удваивается.

, Если у Вас есть доступ к C99, можно также попробовать масштабируемую целочисленную арифметику с помощью int64_t 64-разрядный целый тип. То, которое быстрее, будет зависеть от Вашей аппаратной платформы.

21
задан John Bubriski 24 September 2009 в 18:44
поделиться

23 ответа

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

Тем не менее, было бы проще определить логическую переменную, которой присвоено условие в операторе if (), а затем написать свой код в качестве отрицания этой переменной:

bool myCondition = (....);
if (!myCondition)
{
    ...
}
60
ответ дан 29 November 2019 в 06:03
поделиться

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

Например

class MyClass
{
   public string Prop{ get; set; }
   // ... snip ...
   public bool IsValid
   {
      bool valid = false;
      if((value != null) && 
      (!string.IsNullOrEmpty(value.Prop)) && 
      (possibleValues.Contains(value.prop)))
      {
         valid = true
      }
      return valid;
   }
   // ...snip...
}

Теперь ваш код приложения

MyClass = value = GetValueFromSomewhere();

if( value.IsValie == false )
{
   // Handle bad case here...
}
0
ответ дан 29 November 2019 в 06:03
поделиться

Я бы не стал делать это на C #. Но я делаю это на Python, потому что в Python есть ключевое слово, означающее «ничего не делать»:

if primary_condition:
   pass
elif secondary_condition1:
   do_one_thing()
elif secondary_condition2:
   do_another_thing()

Можно сказать, что {} функционально эквивалентно pass , что это. Но это (для людей) семантически не эквивалентно. pass означает «ничего не делать», а для меня {} обычно означает «раньше был код, а сейчас его нет».

Но в целом, если Я дохожу до того, что даже возникает проблема, затрудняет ли чтение ! перед условием, у меня проблема. Если я пойму, что пишу такой код:

while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key)

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

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

Следующий стиль, в котором один блок должен быть пустым от if-else, считается плохим. для хорошей практики программирования, если вам не нужно писать в блоке if, вам нужно поставить (!) 'Not' в блок if .. нет необходимости писать else

If (условие) // пусто еще // код

можно заменить на

if (! условие) // код

это также сохранение дополнительной строки кода ..

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

1-й:

object value = GetValueFromSomeAPIOrOtherMethod();
var isValidValue = (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop));
if(!isValidValue)
{
    // Do my stuff here, like error handling
}

2cnd:

object value = GetValueFromSomeAPIOrOtherMethod();
if(!isValidAPIValue(value))
{
    // Do my stuff here, like error handling
}
0
ответ дан 29 November 2019 в 06:03
поделиться

Все ли выражения действительно одинаковы? В языках, поддерживающих короткое замыкание, изменение между «и» и «или» может быть фатальным. Помните об использовании && в качестве защиты от проверки других условий.

Будьте осторожны при преобразовании. Сделано больше ошибок, чем можно было ожидать.

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

Я всегда пытаюсь преобразовать такие большие условия в свойство или метод для удобства чтения. Итак, это:

object value = GetValueFromSomeAPIOrOtherMethod();

if((value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop)))
{
    // Do my stuff here, like error handling
}

становится примерно таким:

object value = GetValueFromSomeAPIOrOtherMethod();

if (IsValueUnacceptable(value))
{
    // Do my stuff here, like error handling
}

...

/// <summary>
/// Determines if the value is acceptable.
/// </summary>
/// <param name="value">The value to criticize.</param>
private bool IsValueUnacceptable(object value)
{
    return (value == null) || (string.IsNullOrEmpty(value.Prop)) || (!possibleValues.Contains(value.prop))
}

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

Конечно,

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

Мне нравится вторая версия. Это делает код более чистым. На самом деле это одна из вещей, которую я бы попросил исправить во время проверки кода.

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

Обычно я отвечаю отрицательно .... но я думаю, что хороший стиль программирования основан на согласованности .....

поэтому, если у меня много выражений, выглядят как

if (condition)
{
    // do something
}
else
{
    // do something else
}

Затем случайный «пустой» блок if подходит, например

if (condition)
{ } // do nothing
else
{
    // do something else
}

Причина этого в том, что если ваши глаза что-то видят несколько раз, они с меньшей вероятностью заметят изменение, например крошечный «!». Так что, хотя это плохо делать изолированно, очень вероятно, что кто-то, обслуживающий код, в будущем поймет, что этот конкретный if..else ... отличается от остальных ...

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

if (!step1done)
{}  // do nothing, but we might decide to put something in here later
else if (!step2done)
{
    // do stuff here       
}
else if (!step3done)
{
    // do stuff here       
}

. Это явно подчеркивает последовательный поток состояний, шаги, выполняемые в каждом (даже если это ничего). Я бы предпочел это чем-то вроде ...

if (step1done && !step2Done)
{
    // do stuff here       
}
if (step1done && step2done && !state3Done)
{
    // do stuff here       
}
1
ответ дан 29 November 2019 в 06:03
поделиться

Иногда я попадаю в похожую, но немного отличающуюся ситуацию:

if ( TheMainThingIsNormal () )
    ; // nothing special to do

else if ( SomethingElseIsSpecial () )   // only possible/meaningful if ! TheMainThingIsNormal ()
    DoSomethingSpecial ();

else if ( TheOtherThingIsSpecial () ) 
    DoSomethingElseSpecial ();

else // ... you see where I'm going here

// and then finish up

Единственный способ удалить пустой блок - это создать дополнительную вложенность:

if ( ! TheMainThingIsNormal () )
{
    if ( SomethingElseIsSpecial () )
        DoSomethingSpecial ();

    else if ( TheOtherThingIsSpecial () ) 
        DoSomethingElseSpecial ();

    else // ...
}

Я не проверяю исключение или условия проверки - я просто занимаюсь особыми или разовыми случаями - поэтому я не могу просто выручить раньше времени.

1
ответ дан 29 November 2019 в 06:03
поделиться

Я считаю это неприемлемым (хотя я ' я уверен, что делал это в прошлом), чтобы иметь такой пустой блок. Это подразумевает, что что-то должно быть сделано.

Я вижу, что в других вопросах говорится, что второй способ более удобочитаем. Лично я говорю, что ни один из ваших примеров не особо читабелен. В приведенных вами примерах требуется метод "IsValueValid (...)".

1
ответ дан 29 November 2019 в 06:03
поделиться

Я делаю это, когда мой мозг может легко понять логику успеха, но трудно понять логику неудачи.

Я обычно просто добавляю комментарий "// no op ", чтобы люди знали, что это не ошибка.

1
ответ дан 29 November 2019 в 06:03
поделиться

Если я вижу «если», я ожидаю, что оно что-то сделает.

if(!condition)

гораздо более читабельно.

if(condition) {
  //do nothing
}
else {
  //do stuff
}

по сути гласит: «Если мое условие выполнено, ничего не делайте, в противном случае сделайте что-нибудь ».

Если мы хотим читать ваш код как прозу (какой хороший самодокументирующийся код должен быть в состоянии читать таким образом) , это просто слишком многословно и вводит больше концепций, чем необходимо отпишусь. Используйте знак "!".

2
ответ дан 29 November 2019 в 06:03
поделиться

Ваш вопрос аналогичен моему ответу (упрощение условий) на любимое игнорирование программиста pet peeve's

Для языков, которые не поддерживают конструкцию до, объединение в цепочку множественных NOTs заставляет наши глаза кровоточить

Какой из них легче читать?

Это:

while (keypress != escape_key && keypress != alt_f4_key && keypress != ctrl_w_key)

Или это:

until (keypress  == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)

Я считаю, что последнее легче грокнуть, чем первое. Первый включает слишком много НЕ, а условия И делают логику более липкой , вынуждают вас прочитать все выражение, прежде чем вы сможете быть уверены, что ваш код действительно правильный, и это будет намного сложнее читать, если ваша логика включает сложную логику (влечет за собой объединение большего количества операторов AND, очень липких).

В колледже в нашем классе изучают теорему Де Моргана. Я действительно ценю, что логику можно упростить с помощью его теоремы. Итак, для языковой конструкции, которая не поддерживает оператор until, используйте это:

while !(keypress  == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key)

Но поскольку C не поддерживает оператор while / if без скобок, нам нужно добавить скобки в наш код DeMorgan'd:

while (!(keypress  == escape_key || keypress == alt_f4_key || keypress == ctrl_w_key))

И это что могло спровоцировать комментарий Дэна Си о том, что код ДеМоргана больше режет ему глаза на мой ответ на любимое невежество программиста, домашнее раздражение

Но на самом деле, код ДеМоргана легче читать, чем иметь несколько NOTS и липкое AND

[EDIT]

Ваш код (код ДеМоргана):

object value = GetValueFromSomeAPIOrOtherMethod();

if ( value == null || string.IsNullOrEmpty(value.Prop) 
   || !possibleValues.Contains(value.prop) )
{
    // Do my stuff here, like error handling
}

.. в порядке. Фактически, это то, что делают большинство программистов (особенно из языков, которые не имеют конструкций try / catch / finally с самого начала), чтобы убедиться, что выполняются условия (например, отсутствие использования нулевых указателей, правильные значения и т. Д.) перед продолжением операций.

Примечание: я взял на себя смелость удалить лишние скобки в вашем коде, возможно, вы пришли с языка Delphi / Pascal.

2
ответ дан 29 November 2019 в 06:03
поделиться

Это плохой стиль, рассмотрите несколько очень полезных альтернатив:

Используйте стиль защитного предложения :

object value = GetValueFromSomeAPIOrOtherMethod();

if((value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop)))
{
    return;
}
// do stuff here

Извлеките условное выражение в его собственный метод, это сохраняет вещи логично и легко читается:

bool ValueHasProperty(object value)
{
    return (value != null) && (!string.IsNullOrEmpty(value.Prop)) && (possibleValues.Contains(value.prop));
}

void SomeMethod()
{
    object value = GetValueFromSomeAPIOrOtherMethod();
    if(!ValueHasProperty(value))
    {
        // do stuff here
    }
}
2
ответ дан 29 November 2019 в 06:03
поделиться

Хотя это не всегда практично, я обычно предпочитаю изменить

if (complexcondition){} else {/*stuff*/}

на

if (complexcondition) continue;
/*stuff*/

(или выйти с return , break , так далее.). Конечно, если условие слишком сложное, вы можете заменить его несколькими условиями, все из которых заставят код нарушить то, что он делает. Это в основном относится к типам кода проверки и проверки ошибок, от которых вы, вероятно, захотите выйти, если что-то пойдет не так.

3
ответ дан 29 November 2019 в 06:03
поделиться

Извлеките ваши условия, затем позвоните по телефону

if(!ConditionsMetFor(value))
{
   //Do Something
}
3
ответ дан 29 November 2019 в 06:03
поделиться

Простое использование части else недопустимо. Вам не нужно утруждать себя применением правила Де-Моргана, только не всего выражения. То есть перейдите от if (cond) к if (! (Cond)) .

9
ответ дан 29 November 2019 в 06:03
поделиться

Я считаю это совершенно неприемлемым.

Единственная причина - избегать единственного отрицания и пары скобок вокруг выражения. Я согласен, что выражения в вашем примере ужасны, но они недопустимо запутаны с самого начала! Разделите выражение на части приемлемой ясности, сохраните их в логических значениях (или сделайте из них методы) и объедините их, чтобы создать условие if-statement.

Один похожий дизайн, который я часто использую, - это ранний выход. Я не пишу такой код:

if (validityCheck1)
{
    if (validityCheck2)
    {
        // Do lots and lots of things
    }
    else
    {
        // Throw some exception, return something, or do some other simple cleanup/logic (version 2)
    }
}
else
{
    // Throw some exception, return something, or do some other simple cleanup/logic. (version 1)
}

Вместо этого я пишу это:

if (!validityCheck1)
{
    // Throw some exception, return false, or do some other simple logic. (version 1)
}

if (!validityCheck2)
{
    // Throw some exception, return false, or do some other simple logic. (version 2)
}

// Do lots and lots of things

У этого есть два преимущества:

  1. Лишь несколько вариантов ввода недопустимы, и они просты в обращении. С ними нужно работать немедленно, чтобы мы могли как можно скорее выбросить их из нашей ментальной модели и полностью сосредоточиться на важной логике. Особенно, когда во вложенных операторах if выполняется несколько проверок действительности.

  2. Блок кода, который обрабатывает допустимые варианты, обычно будет самой большой частью метода и будет содержать собственные вложенные блоки. Он будет намного менее загроможден, если сам этот блок кода не вложен (возможно, несколько раз) в оператор if.

Таким образом, код будет более читаемым и его легче рассуждать.

9
ответ дан 29 November 2019 в 06:03
поделиться

Я должен предисловие к этому, сказав, что мои личные предпочтения, но я обычно вытаскиваю логику проверки из кода в ее собственную функцию проверки. В этот момент ваш код становится более «аккуратным», если вы просто говорите:

if(!ValidateAPIValue(value))

Это, на мой взгляд, кажется более кратким и понятным.

28
ответ дан 29 November 2019 в 06:03
поделиться

Наличие пустого блока if с операторами в else - это ... просто плохой стиль. Извини, это одна из моих любимых мозолей. В этом нет ничего функционально неправильного, просто из-за него у меня текут глаза.

Просто! из оператора if и поместите туда свой код. ИМХО это уменьшает шум и делает код более читабельным.

55
ответ дан 29 November 2019 в 06:03
поделиться

Это не очень хорошая практика. Если бы вы использовали рубин, вы бы сделали:

unless condition
  do something
end

Если ваш язык не позволяет этого, вместо выполнения

if(a){}else{something}

выполните

if(!a){something}
1
ответ дан 29 November 2019 в 06:03
поделиться

I'm a fan of DeMorgan's Rule which takes your ex3 and produces your ex2. An empty if block is a mental block imo. You have to stop to read the nothing that exists - then you have to wonder why.

If you have to leave comments like // This left blank on purpose; then the code isn't very self-explanatory.

0
ответ дан 29 November 2019 в 06:03
поделиться
Другие вопросы по тегам:

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