C에서 1,000,000,000을 1000 * 1000 * 1000으로 쓰는 이유는 무엇입니까?


142

Apple이 만든 코드에는 다음과 같은 줄이 있습니다.

CMTimeMakeWithSeconds( newDurationSeconds, 1000*1000*1000 )

표현 할 이유가 있습니까 1,000,000,000로는 1000*1000*1000?

1000^3그런 문제가 되지 않습니까?


45
코드의 명확성과 가독성. C에서, 또는 '을 구분 기호로 넣을 수 없으므로 다음으로 가장 좋은 것은 곱셈에서 값을 계산하는 것입니다. ^는 C의 배타적 OR에 관련이없는 연산자입니다.
Iwillnotexist Idonotexist

54
그것은 특히 같은 시간 동안 사용 : 2 * 60 * 60 .. 쉽게 2 시간입니다 ..
Idali

53
나는 1,000,000,000이 유효한 구문이 아니라고 생각한다
paparazzo

15
그건 그렇고, 현대의 프로그래밍 언어는 예를 들어 Swift와 같은 것을 작성하는 대체 방법이 1_000_000_000있습니다. 그러나 시간 상수가 있으면 더 어렵습니다. 쓰는 30 * 60것보다 쓰는 것이 더 읽기 쉽습니다 (30 분 초) 1800. 실제로 단위를 작성할 수있는 언어가 있습니다. 예를 들어 meters, 잘못된 할당으로부터 자신을 보호 할 수 있습니다.
Sulthan

29
^지수 또는 거듭 제곱 연산자가 아닌 XOR입니다.
3Dave

답변:


200

곱셈 방식으로 상수를 선언하는 한 가지 이유는 가독성을 높이고 런타임 성능에는 영향을 미치지 않기 때문입니다. 또한 작가가 숫자에 대해 곱셈 방식으로 생각하고 있음을 나타냅니다.

이걸 고려하세요:

double memoryBytes = 1024 * 1024 * 1024;

다음보다 분명히 낫습니다.

double memoryBytes = 1073741824;

후자는 언뜻보기에 1024의 세 번째 힘을 보지 않습니다.

Amin Negm-Awad가 언급했듯이 ^연산자는 이진수 XOR입니다. 많은 언어에는 내장 된 컴파일 타임 지수 연산자가 없기 때문에 곱셈입니다.


13
지수 연산자가있는 언어에서는 반드시 '^'일 필요는 없습니다. 예를 들어 포트란에서는 '**'입니다.
jamesqf

4
: 당신은 또한 @chux에서 아래의 대답에 주어진 중요한주의를 가리키는 링크를 포함해야 stackoverflow.com/a/40637622/1841533을 (영업 이익이 '맞 손에 매우 취약하다 "C"를 태그 특히 측면 연산은 모든 용어가 더 작은 유형으로 제한되는 것처럼 보이므로 곱셈이 오버플로 될 수 있습니다). securecoding.cert.org/confluence/display/c/… 일반적인 경우를 피하는 데 도움이 될 수 있습니까?
Olivier Dulac

4
또한 계산은 컴파일 타임에 수행됩니다. C 표준에서는 구현시 언어의 다양한 기능에 대해 컴파일 타임에 상수 표현식을 계산할 수 있어야하며이 예제에서와 같이 상수 표현식을 사용할 때 해당 표현식이 참이라고 가정 할 수 있습니다.
ouah

13
메모리 양을 두 배로 저장 하시겠습니까? 잠재적 인 오류 원인 인 것 같습니다.
JAB

7
@supercat 나는 그것을 알고 있지만 double을 사용하면 메모리 범위의 일부를 원 x하고 하위 범위의 크기를 얻기 위해 나누는 경우가 있습니다 ... 갑자기 분수가 있습니다. 이를 보완하기 위해 추가 로직이 필요할 수 있습니다.
JAB

73

왜 안돼 1000^3?

결과 1000^3는 1003 ^입니다. 비트 XOR 연산자입니다.

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

57
^C / C ++ / 오브젝티브 C 등 계산기에 보통 수단 엑스 투 - Y 전력의 조작 수단 XOR.
Tamás Zahola

5
Bah, 1000과 3의 비트는 겹치지 않습니다. 이것은 너무 잘못 보인다 .
Yakk-Adam Nevraumont

19
비트가 겹칩니다. 그러나 1은 아닙니다. :-]
Amin Negm-Awad

6
@ Yak : 실제로, 그것은 너무 잘못 보인다! ... 많은 사람들이 "A ^ B"가 항상 A + B를 준다고 생각하지 않기를 바랍니다 (그러나 일부는 두려워 할 수도 있습니다 ...)
Olivier Dulac

71

사용 하지 않는 이유 가 있습니다 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정수 값을 정확하게 나타낼 수 있는지 여부를 알 수 있습니다-1e9보다 큰 값의 우려 사항. ( DBL_EPSILON와 참조 DBL_DIG).

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

5
매우 중요한 말! securecoding.cert.org/confluence/display/c/… 많은 경우에 도움이 될 수 있습니까?
Olivier Dulac

2
A double는 최대 2 ^ 53 ≈ 9e15의 모든 정수를 정확하게 나타낼 수 있습니다.
Edgar Bonet

3
@EdgarBonet binary64 는 최대 약 9e15의 정수 를 나타낼 수 있습니다. 그러나 C는 doublebinary64의 사용을 지정하지는 않지만 매우 일반적으로 사용됩니다. C 사양에 따라 최대 1e9 정도의 값을 정확하게 표현할 수 있습니다. 일반적인 관행을 지정하거나 의존하도록 코드를 작성할지 여부에 따라 다릅니다.
chux-복원 Monica Monica

4
모두를 @Patrick 1000하고 1000000000000있습니다 상수 정수 . 각각 독립적으로으로부터 선택된 형태를 int, long또는 long long. 컴파일러는 정수 상수가 맞는 3의 첫 번째 유형을 사용합니다 . 에서 각각의 수학으로 1000 * 1000 * 1000 * 1000수행됩니다 . 제품에 32 비트가 넘칩니다 . 오버플로 없음 으로 분명히 표현 가능합니다. 대상의 유형은 이 "="정의의 오른쪽에 영향을 미치지 않습니다. int1000intint1000000000000long longlong long Duration
chux-복원 Monica Monica

2
곱셈에서 더 넓은 유형을 먼저 배치하는 것이 중요합니다. 16 비트 int이면 long x = 1000 * 1000 * 1000L;오버플로가 발생하지만 long x = 1000L * 1000 * 1000;그렇지 않습니다.
전 nihilo

51

가독성을 위해.

영 ( 1 000 000 000또는 1,000,000,000) 사이에 쉼표와 공백을 넣으면 구문 오류가 발생 1000000000하며 코드에 포함 된 숫자가 정확히 몇 개인 지 알기가 어렵습니다.

1000*1000*1000우리 눈이 청크를 더 쉽게 처리 할 수 ​​있기 때문에 10 ^ 9임을 알 수 있습니다. 또한 컴파일러는 런타임 비용을 constant로 대체하기 때문에 런타임 비용이 없습니다 1000000000.


5
참고로 최근에 배운 숫자 구분 기호 개념이 있습니다. Java는 잠시 동안 그것을 가지고 있었고 C # 7.0은 그것을 얻을 수 있습니다. 모든 언어가 눈에 띄는 기능을 갖기를 바랍니다. :)
iheartcsharp

1
사용하는 컨텍스트에 따라 1,000,000,000구문 오류가 발생하지 않으면 다른 의미가 있습니다. 예 :CMTimeMakeWithSeconds( newDurationSeconds, 1,000,000,000 )
Ross Ridge

2
@ JMS10 C #은 VS15 프리뷰 버전을 설치하면 이미이를 가지고 있습니다 :1_000_000_000
user1306322

2
파이썬도 _분리 자로 사용됩니다 :)
Wayne Werner

2
그리고 C ++은 최근 'C ++ 14에서 구분 기호를 얻었 으므로 사용할 수 있습니다 1'000'000'000. ( 1,000,000,000쉼표 연산자 또는 4 개의 고유 한 매개 변수로 잘못 해석 될 수 있고 _1_000_000_000유효하지만 (아마도 잘못된) 변수 이름 이기 때문에 선택되었습니다 .)
Justin Time-Reinstate Monica

27

가독성을 위해. 비교 _를 위해 Java는 가독성을 높이기 위해 숫자를 지원합니다 ( Derek Foster의 제안 : Project Coin / JSR 334에 대한 이진 리터럴에 대한 응답 으로 Stephen Colebourne이 처음 제안했습니다 ). 하나는 1_000_000_000여기에 쓸 것입니다.

가장 오래된 지원부터 최신까지 대략 연대순으로 :

언어가 지원해야한다는 것을 깨닫는 것은 비교적 새로운 기능입니다 (그리고 Perl이 있습니다). chux @의 탁월한 답변과 1000*1000...마찬가지로 부분 솔루션이지만 최종 결과가 큰 유형이더라도 프로그래머가 곱셈을 오버플로하지 못하도록 버그가 발생합니다.


많은 현대 프로그래밍 언어, 예를 들어 Swift가 동일합니다. 새로운 것은 없다.
Sulthan

AFAIK, 이것은 Perl에서 온 것입니다. PL / M은 같은 목적을 위해 $를 사용 예 : 0100 $ 0010b로 설정 됨으로써
ninjalj

1
그것은 이다 하지만, 신종. Java 기능은 아마도 5 살입니다. 이 구문을 지원하는 대부분의 다른 언어는 매우 새롭습니다. Swift 자체는 불과 몇 년 전입니다. Python은 아직 릴리스되지 않은 3.6의 지원을 추가합니다.
johncip

2
Ada는 현재 33 년 동안 정수 리터럴에서 밑줄을 지원했습니다.
피터-모니카 복원 복원

1
@ djechlin : 나는 대략 시간 순서대로 더 많은 정보를 추가 할 수있는 자유를 얻었습니다. 전에는 Project Coin 스레드로 판단했을 때 Stephen Colebourne이 Fandom 및 / 또는 Ruby의 정수 리터럴로 밑줄을 생각했을 것입니다. 루비는 아마도 Perl과 Ada의 Perl에서 아이디어를 얻었을 것입니다.
ninjalj

7

1,000,000,000양식 을 읽고 더 쉽게 이해할 수 있습니다 .

기술적 측면에서 나는 직접 수와 곱셈 사이에 차이가 없다고 생각합니다. 컴파일러는 어쨌든 상수 10 억 개의 숫자로 생성합니다.

objective-c에 대해 말하면 1000^3pow에 대한 그러한 구문이 없기 때문에 작동하지 않습니다 (xor입니다). 대신 pow()기능을 사용할 수 있습니다. 그러나이 경우 최적이 아니며 컴파일러에서 생성 한 상수가 아닌 런타임 함수 호출입니다.


3

이유를 설명하기 위해 다음 테스트 프로그램을 고려하십시오.

$ 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
$

1
@pjvandehaar Wikipedia 기사를 읽고 언어를 배우는 것은 좋지 않습니다.
피터-복원 모니카

0

십진수에 대해 C에서 유사한 효과를 얻는 또 다른 방법은 리터럴 부동 소수점 표기법을 사용하는 것입니다. 이중 값이 정밀도 손실없이 원하는 숫자를 나타낼 수있는 한.

IEEE 754 64 비트 double은 문제없이 음수가 아닌 정수 <= 2 ^ 53을 나타낼 수 있습니다. 일반적으로 long double (80 또는 128 비트)은 이보다 더 길어질 수 있습니다. 변환은 컴파일 타임에 수행되므로 런타임 오버 헤드가 없으며 예상치 못한 정밀도 손실이 있고 컴파일러가 좋은 경우 경고가 표시 될 수 있습니다.

long lots_of_secs = 1e9;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.