2016-11-16 3 views
132

В коде, созданный Apple, есть такая строка:Зачем писать 1000 000 000 как 1000 * 1000 * 1000 в C?

CMTimeMakeWithSeconds(newDurationSeconds, 1000*1000*1000) 

Есть ли какая-либо причина, чтобы выразить 1,000,000,000 как 1000*1000*1000?

Почему нет 1000^3 в этом отношении?

+40

Ясность и удобочитаемость кода. Вы не можете поставить или «как разделители на C», поэтому следующая лучшая вещь - вычисление значения из умножения.^- несвязанный оператор в С - исключительный ИЛИ. –

+51

он особенно используется для длительностей, таких как: 2 * 60 * 60 .. его легко заметить, что за 2 часа .. – Idali

+51

Для одного я подозреваю, что 1 000 000 000 недопустим синтаксис – Paparazzi

ответ

190

Одна из причин объявления констант мультипликативным способом заключается в улучшении читаемости, в то время как производительность во время выполнения не изменяется. Кроме того, чтобы указать, что писатель многократно думал о количестве.

Рассмотрим это:

double memoryBytes = 1024 * 1024 * 1024; 

Это явно лучше, чем:

double memoryBytes = 1073741824; 

как последний не выглядит, на первый взгляд, третья сила 1024.

Как Амина Негм-Авад упомянул, что оператором ^ является двоичный код XOR. На многих языках отсутствует встроенный оператор экспоненциального компиляции, поэтому умножение.

+12

И на языках, которые имеют оператор экспоненциальности, это не обязательно «^». Например, в Фортране это «**». – jamesqf

+4

Вы также должны указать ссылку, указывающую на важный оговорку, приведенную ниже, из @chux: http://stackoverflow.com/a/40637622/1841533 (особенно, поскольку OP с меткой «c», который очень восприимчив к эта операция «с большой стороны», похоже, имеет все термины, ограниченные меньшим типом, и поэтому проблема умножения может переполняться ». https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow может помочь избежать общий случай? –

+3

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

72

Почему не 1000^3?

Результатом является 1000^3 1003. ^ является оператором битового исключающее ИЛИ.

Даже это не касается самой Q, я добавляю разъяснение. x^y делает не всегда оценивается до x+y, как в примере опроса. Вам нужно каждый бит. В случае примера:

1111101000₂ (1000₁₀) 
0000000011₂ (3₁₀) 
1111101011₂ (1003₁₀) 

Но

1111101001₂ (1001₁₀) 
0000000011₂ (3₁₀) 
1111101010₂ (1002₁₀) 
+3

сэр, я не понимаю, как 1003^3 - 1003. Калькулятор Google и Mac показывает 1000^3 = 1,000,000,000. Вы можете объяснить? – Mahesh

+55

Оператор '^' означает XOR в C/C++/Objective-C и т. Д. В калькуляторах обычно это означает силу x-to-the-y. –

+5

Бах, бит 1000 и 3 не перекрываются. Это выглядит так неправильно. – Yakk

6

Может быть проще читать и получить какую-то ассоциацию с 1,000,000,000 формой.

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

Если вы говорите об объективе-c, то 1000^3 не будет работать, потому что нет такого синтаксиса для pow (это xor). Вместо этого можно использовать функцию pow(). Но в этом случае он не будет оптимальным, это будет вызов функции времени выполнения, а не сгенерированная константа компилятора.

49

Для удобства чтения.

Размещение запятых и пробелов между нулями (1 000 000 000 или 1,000,000,000) будет производить синтаксическую ошибку, и с 1000000000 в коде делает его трудно увидеть, как много нулей есть.

1000*1000*1000 делает очевидным, что это 10^9, потому что наши глаза легче обрабатывают куски.Кроме того, нет времени на запуск, поскольку компилятор заменит его на константу 1000000000.

+5

FYI, есть концепция разделителей цифр, о которых я узнал недавно. У Java это было какое-то время, и C# 7.0 может получить его. Я желаю, чтобы все языки имели эту функцию для глазных конфет. :) – JMS10

+1

В зависимости от контекста с использованием '1,000,000,000' не будет возникать синтаксическая ошибка, это будет означать что-то еще. Например, 'CMTimeMakeWithSeconds (newDurationSeconds, 1,000,000,000)' –

+1

@ JMS10 C# уже имеет его, если вы устанавливаете версию предварительного просмотра VS15, может быть записано как '1_000_000_000' – user1306322

24

Для удобства чтения. Для сравнения, Java поддерживает _ в цифрах, чтобы улучшить читаемость (сначала предложенный Стивеном Коулбурном как reply to Derek Foster's PROPOSAL: Binary Literals для Project Coin/JSR 334). Здесь можно было бы написать 1_000_000_000.

В примерно в хронологическом порядке, от самой старой поддержки к новым:

Это относительно новая функция языка, чтобы понять, что они должны поддерживать (а затем есть Perl). Как и в отличном ответе chux @, 1000*1000... является частичным решением, но открывает программиста до ошибок при переполнении умножения, даже если конечный результат является большим типом.

+0

Многие современные языки программирования имеют одинаковое значение, например. Swift. Ничего нового. – Sulthan

+0

AFAIK, это происходит от Perl. PL/M использовал $ для той же цели, например: 0100 $ 0010B – ninjalj

+1

Это * довольно просто. Java-функции, возможно, 5 лет. Большинство других языков, поддерживающих этот синтаксис, довольно новы - самому Swift всего лишь несколько лет. Python добавляет поддержку в 3.6, которая еще не выпущена. – johncip

61

Есть причины не использовать 1000 * 1000 * 1000.

С 16-разрядным int, 1000 * 1000 переполнение. Таким образом, использование 1000 * 1000 * 1000 снижает переносимость.

С 32-битной int следующие переполнения.

long long Duration = 1000 * 1000 * 1000 * 1000; // overflow 
long long Duration = 1000000000000; // no overflow, hard to read 

Предполагают, что свинец значение соответствует типу назначения для удобства чтения, портативности и правильности.

double Duration = 1000.0 * 1000 * 1000; 
long long Duration = 1000LL * 1000 * 1000 * 1000; 

Также может просто использовать e обозначения для значений, которые точно представима как double. Конечно, это приводит к пониманию того, может ли double точно представлять целое числовое значение - что-то касающееся значений больше 1е9. (См. DBL_EPSILON и DBL_DIG).

long Duration = 1000000000; 
// vs. 
long Duration = 1e9; 
+5

Очень важное замечание! https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow может помочь во многих случаи? –

+1

«double» может точно представлять все целые числа до 2^53 ≈ 9e15. –

+2

@EdgarBonet Правда, что [binary64] (https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64) может представлять целое число примерно до 9э15. Но C не указывает «двойное» использование двоичного кода64, хотя он очень часто используется. В C spec значения до 1e9 или около того точно представлены. Это зависит от того, хотите ли вы кодировать спецификации или полагаться на обычную практику. – chux

2

Для иллюстрации причины рассмотрим следующую тестовую программу:

$ cat comma-expr.c && gcc -o comma-expr comma-expr.c && ./comma-expr 
#include <stdio.h> 

#define BILLION1 (1,000,000,000) 
#define BILLION2 (1000^3) 

int main() 
{ 
     printf("%d, %d\n", BILLION1, BILLION2); 
} 
0, 1003 
$ 
+0

Оператор запятой объясняется на https://en.wikipedia.org/wiki/Comma_operator – pjvandehaar

+0

@pjvandehaar Я бы не рекомендовал изучать язык, читая статьи в Википедии. –

0

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

IEEE 754 64-битные двойной может представлять любое неотрицательное целое число < = 2^53 без проблем.Как правило, длинные двойные (80 или 128 бит) могут идти еще дальше. Конверсии будут выполняться во время компиляции, поэтому накладные расходы не будут выполняться, и вы, скорее всего, получите предупреждения, если произойдет непредвиденная потеря точности, и у вас хороший компилятор.

long lots_of_secs = 1e9;