Я недавно сталкивался с этой идиомой программирования:
const float Zero = 0.0;
который затем используется в сравнениях:
if (x > Zero) {..}
Может ли кто-нибудь объяснить, действительно ли это более эффективно, доступно для чтения или сопровождения, чем:
if (x > 0.0) {..}
ПРИМЕЧАНИЕ: я могу подумать о других причинах для определения этой константы, мне просто интересно, как ее использовать в этом контексте.
x
имеет типfloat
, тоx > 0.0
форсирует повышениеdouble
, которое может быть менее эффективным. Это не очень хорошая причина для использования именованной константы, просто для того, чтобы убедиться, что ваши константы имеют правильный тип (например0f
,float(0)
илиdecltype(x)(0)
).13.37
это неfloat
такdouble
. Так что, если вы хотели,float
то вполне возможно, что ваш репетитор был прав. В некоторых контекстах (например, присвоение float)13.37
будет неявно преобразовано в то,float
что вы хотели, а в других контекстах (например, вывод типа шаблона) это не будет, тогда какstatic const float
всегда начинается с того типа, который вы намеревались. Следовательно, более безопасный тип. Имейте в виду, так будет13.37f
! Однако есть и другие причины избегать макроса, кроме «безопасности типов», так что вполне вероятно, что преподаватель дал вам плохой аргумент.Ответы:
Возможные причины: кэширование, присвоение имен или принудительный тип.
Кэширование (не применимо)
Вы хотите избежать затрат на создание объекта во время акта сравнения. В Java пример будет
это включает в себя довольно тяжелый процесс создания и лучше обслуживается с использованием предоставленного статического метода:
Это позволяет проводить сравнения без повторных затрат на создание, поскольку JDM во время инициализации предварительно кэширует BigDecimal.
В случае того, что вы описали, примитив выполняет ту же работу. Это в значительной степени избыточно с точки зрения кэширования и производительности.
Именование (маловероятно)
Первоначальный разработчик пытается обеспечить единое соглашение об именах для общих значений во всей системе. Это имеет некоторые достоинства, особенно с необычными значениями, но базовое значение, равное нулю, того стоит только в случае с кэшированием ранее.
Тип принуждения (скорее всего)
Первоначальный разработчик пытается заставить конкретный тип примитива гарантировать, что сравнения приводятся к их правильному типу и, возможно, к определенному масштабу (числу десятичных знаков). Это нормально, но простое имя «ноль», вероятно, недостаточно подробно для этого варианта использования, при этом ZERO_1DP является более подходящим выражением намерения.
источник
typedef
сохранит тип переменной ровно в одном месте и позволит изменить его без изменения кода.0.0f
.byteVar1 = byteVar2 Or CB128
кажется немного лучше, чемbyteVar1 = byteVar2 Or CByte(128)
. Конечно, было бы лучше иметь правильный числовой суффикс для байтов. Поскольку C # продвигает операнды побитовых операторов,int
даже если результат гарантированно помещается в abyte
, проблема здесь не так актуальна.Это из-за "Toolg Nagging"
Возможная причина, которую я не вижу в этом списке, заключается в том, что многие качественные инструменты отмечают использование магических чисел . Часто плохая практика - бросать магические числа в алгоритм, не делая их ясно видимыми для последующего изменения, особенно если они дублируются в нескольких местах кода.
Таким образом, хотя эти инструменты и подходят для обозначения таких проблем, они часто генерируют ложные срабатывания в ситуациях, когда эти значения безвредны и, скорее всего, являются статическими или просто являются значениями инициализации.
И когда это происходит, иногда вы сталкиваетесь с выбором:
О производительности
Это зависит от языка, который я предполагаю, но это довольно распространено в Java и не влияет на производительность, так как значения встроены во время компиляции, если они являются реальными константами
static final
. Это не повлияет на C или C ++, если они объявлены как константы или даже как макросы препроцессора.источник
Это может иметь смысл, поскольку оно явно определяет
Zero
типfloat
.По крайней мере в C и C ++ значение
0.0
имеет типаdouble
, в то время как эквивалентноеfloat
это0.0f
. Таким образом, еслиx
вы сравниваете это тоже всегдаfloat
поговоркав то время как на самом деле продвигать,
x
чтобыdouble
соответствовать типу,0.0
который может привести к проблемам (особенно с тестами на равенство). Конечно, сравнение без конвертации будеткоторый делает так же, как
Тем не менее, я думаю, что было бы гораздо полезнее включать предупреждения о преобразованиях в компиляторе, а не заставлять пользователей писать неуклюжий код.
источник
Прежде всего, здесь ноль определяется как
float
, а неint
. Конечно, это ничего не влияет на сравнение, но в других случаях, когда используется эта константа, это может иметь значение.Я не вижу другой причины, почему
Zero
здесь объявлена константа. Это просто какой-то стиль кодирования, и лучше следовать этому стилю, если он используется везде в этой определенной программе.источник
Это почти точно так же эффективно во время выполнения (если ваш компилятор не очень примитивен) и очень немного менее эффективно во время компиляции.
Что касается того, является ли это более читабельным, чем
x > 0
... помните, что есть люди, которые честно, искренне думают, что COBOL была отличной идеей и удовольствием работать с ними, а также есть люди, которые думают точно так же о C. (По слухам, это то, что даже существуют некоторые программисты с таким же мнением о C ++!) Другими словами, вы не достигнете общего согласия по этому вопросу, и, вероятно, не стоит бороться.источник
Если вы писали общий (т.е. не специфичный для типа) код, то вполне возможно.
zero()
Функция может применяться к любому алгебраическому типа или любому типу , который представляет собой группу WRT дополнения. Это может быть целое число, это может быть значение с плавающей запятой, это может быть даже функция, если ваша переменная, скажем, сама является функцией в некотором линейном пространстве (например, x является линейной функцией вида z -> a_x * z + b_x), а затемzero()
предоставляет функции с a и b обаzero()
базового типа.Таким образом, вы ожидаете такой код, скажем, на C ++, возможно (хотя a
zero()
не очень распространенный AFAIK), или на Julia, и, возможно, на других языках.источник