정수 상수에서 밑줄을 허용하지 않는 언어에서는 10 억 상수를 만드는 것이 좋은 방법입니까?


39

정수 리터럴로 밑줄을 허용하지 않는 언어에서는 10 억 상수를 만드는 것이 좋습니다. 예를 들어 C ++에서 :

size_t ONE_BILLION = 1000000000;

확실히, 우리는 100과 같은 작은 숫자에 대한 상수를 생성해서는 안됩니다. 그러나 9 개의 0을 사용하면 다음과 같이 0을 남기거나 코드에 여분의 숫자를 추가하는 것이 쉽습니다.

tv_sec = timeInNanosec / 1000000000;
tv_nsec = timeInNanosec % 1000000000;

24
나는 여기의 모든 사람들이 NO에 투표하기를 바랍니다 . 그렇게하면 언젠가 내 은행은 프로그래머가 상수를 사용하지 않고 0을 잘못 배치했기 때문에 10 억 달러를 내 계좌로 이체 할 것입니다! :)
Reactgular

43
적은 수의 상수를 생성하지 않는 이유는 무엇입니까? 100은 무엇을 의미합니까? 문맥이 없으면 마법 번호입니다.
Allan

4
@MathewFoscarini 일반적으로 실수는 어느 쪽이든 갈 수 있습니다. 그러나 은행에 관한 한 실수는 항상 당신에게 불리합니다.
emory

23
고려 쓰기 1e9, 10^9또는 1_000_000_000언어 경우는 지원을 사용하고 있습니다.
hammar

답변:


33

대부분의 언어에는 일종의 지수 표기법이 있습니다. 백만은 1e6(1의 10 배에서 6의 거듭 제곱을 의미)입니다. 이것은 기본적으로 대부분의 제안보다 더 나은 문제를 해결합니다.

C와 같은 많은 언어에서 과학적 표기법부동 소수점 유형을 정의하고 있습니다. 실제로 정수가 필요한 경우 불행합니다. 그러나 수식에서 암시 적 변환을 피하기 위해 해당 상수를 쉽게 형식 캐스팅 할 수 있습니다.

n / int(1e9) 10 억으로 나눕니다.

귀하의 예에서 물리량 (나노초 단위)을 처리 할 때 일반적으로 정수가 올바른 유형인지 묻습니다. 실제로 double측정 가능한 양을 처리 할 때 부동 소수점 이 더 적합 할 수 있습니다 (물론을 선호하는 경우도 있음 long long).


6
나는 NANOSECONDS_IN_ONE_SECOND 솔루션이 훨씬 선명하고 깔끔한 생각
토마스 Bonini을

1
질문은 정수 자유주의에 관한 것이며 과학적 표기법을 사용할 것을 제안합니다. 이를 수행 할 것인지 상수를 정의 할 것인지는 질문에서 요구되지 않은 코드를 구성하는 문제입니다. 상수를 정의하는 것은 제한 추상화, 내가 더 잘 추상화 달성하기 위해 매크로 변환 기능을 / 작성합니다 추가
wirrbel

1
부동 소수점 수의 일반적인 반올림 차이 문제를 위험에 빠뜨리지 않도록 매우 큰 double을 int로 캐스팅합니까?
Philipp

정규 정밀도 정수 유형의 경우 배정 밀도 부동 소수점을 사용하여 변환하는 한 문제가되지 않습니다. 당신은 long long범위의 값을 사용할 때 맞습니다 .
wirrbel

145

NANOSECONDS_IN_ONE_SECOND라는 이름을 대신 표시하십시오.

생각할 수 있다면 더 짧고 더 나은 이름입니다.


58
나는 말할 Nanoseconds_Per_Second것이지만 이것은 내 의견으로는 정답입니다.
KChaloux

8
@Mathew 나는 당신의 요점을 얻지 못합니다. 미터당 밀리미터를 말하는 데 아무런 문제가 없습니다. 당신은 그것이 초 단위로 10 억 분의 1 초를 의미하는 여분의 것을 암시 할 수도 있지만, 그것을 다시 언급하는 데 아무런 문제가 없습니다. 1 + 1 = 2와 같습니다. "x 당 y"는 x와 y가 "반 다스 당 단위"또는 "밀리 초당 나노초"와 같이 x와 y가 분리되어있을 때 더 의미가 있습니다.
Mark Canlas

7
@MathewFoscarini 사실, 아니,이 맥락에서는 그렇지 않다. 그렇다면 상수라는 이름 NANOSECONDS은 적용 대상을 알 수 없으므로 의미가 없습니다. 마찬가지로, NANOSECONDS_PER_MICROSECOND비슷한 유효한 상수가 의미가 있습니다.
이즈 카타

5
@MathewFoscarini, "미터당 밀리미터"는 변환시 단위를 제거하여 원시 값을 얻는 방법입니다. 1mm/1m = 1000, 어떤 정확히 여기 수행되고 있는지의 포인트입니다.
zzzzBov

11
왜 이렇게 많이 타이핑합니까? NS_PER_SEC나노초를 다루어야하는 사람에게는 분명해야합니다.
Rex Kerr

67

상수는 숫자 의미를 제공하기위한 것입니다. 추가 의미에 없다 ONE_BILLION1000000000. 실제로 자연 언어에서 10 억은 다른 무언가 (천만 또는 백만 백만)를 의미하기 때문에 더 혼란 스럽습니다! 더 짧게 작성하려면 프로그래밍 언어에서 과학적 표기법을 사용할 수 있습니다 1e9. 그렇지 않으면 @JohnB에 동의합니다.이 숫자는 실제로 1 초의 나노 초 수를 의미하므로 이름을 지정하십시오.


9
다른 언어로 된 10 억은 다른 양의 0을 의미한다는 것을 잘 지적합니다.
frozenkoi

3
일반 언어를 자연 언어로 바꾸는 것이 좋습니다. regular는 다른 것을 의미합니다 ...
jk.

언어에서 "십억"의 다른 해석은 좋은 지적입니다! 답을 두 번 올릴 수없는 이유는 무엇입니까?
DSF

3
다른 언어가 필요하지 않습니다. 다른 나라도 필요하지 않습니다. 영국 영어에서 "십억"은 1974 년 이전과 이후 공식 통신 (매체 및 정부)에서 다른 것을 의미하며, 두 가지 용도가 여전히 존재합니다.
Jörg W Mittag

1
" 10000000000.에 ONE_BILLION에 추가 의미가없는 나는 동의 (힌트 : 나는 의도적으로 당신을 잘못 인용하고 또 다른 제로 추가, 나는 그것을 언급하지 않았다면 눈치 챘을 것이다?)..
키이스 톰슨

27

한두 가지 사용법에는 다음 규칙을 사용합니다.

tv_sec = timeInNanosec / (1000 * 1000 * 1000);
tv_nsec = timeInNanosec % (1000 * 1000 * 1000);

그것은 완벽하게 자명하고, 일정하게 컴파일되어 망치기가 어렵습니다.

또한 다음과 같은 경우에 매우 유용합니다.

var Time = 24 * 60 * 60;

우리가 하루에 몇 초 만에 이야기하고 있는지 쉽게 알 수 있습니다.


이것이 제가 보통하는 일입니다. 또한 어제 NANOSECONDS_IN_ONE_SECOND를 정의하고 오늘 NANOSECONDS_PER_SECOND를 정의한다는 것을 잊지 않을 이점이 있습니다. 그리고 아마도 내일 ONE_AMERICAN_BILLION입니다.
Thomas Padron-McCarthy

확실히 'SecondsInOneDay = 24 * 60 * 60'이 더 쉬운가요?
JBR 윌킨슨

@JBRWilkinson 확실히, 내 초기 스 니펫은 클래스를 사용하고 instance.Time = ...있었지만, 나는 그것을 바보처럼
만들었

3
C 또는 C ++에서 (1000 * 1000 * 1000)유형 int은 16 비트이면되므로 오버플로 할 수 있습니다. 당신은 (1000L * 1000L * 1000L)그것을 피하기 위해 쓸 수 있습니다 .
Keith Thompson

나는 이것을 많이한다. 잘 작동합니다.
vy32

10

값의 길이는 상수가 필요한지 여부를 정의하는 것이 아닙니다.

입력하는 것을 피하기 위해 상수를 사용하여 마법의 숫자 를 피하십시오.

예를 들어 다음은 완벽하게 유효한 상수입니다.

public static final int CLOSE_CURSORS_AT_COMMIT = 1;
public static final int CONCUR_READ_ONLY = 2;
public static final int CONCUR_UPDATABLE = 3;
public static final int FETCH_FORWARD = 4;
public static final int FETCH_REVERSE = 5; 
public static final int FETCH_UNKNOWN = 6;
public static final int HOLD_CURSORS_OVER_COMMIT = 7;
public static final int TYPE_FORWARD_ONLY = 8;
public static final int TYPE_SCROLL_INSENSITIVE = 9;
public static final int TYPE_SCROLL_SENSITIVE = 10;

사용하다:

public static final int NANOSECS_PER_SECOND = 1000000000;

(코드 샘플은 Java로되어 있으며 선호하는 언어로 번역됩니다)


3
+1 명명 된 숫자는 거의 쓸모가 없습니다. 상수의 목적은 그 숫자에 의미를 부여합니다. 그들은 무엇을 상징합니까? 그들이 계수하거나 제한하거나 공식적으로 명명 한 계수는 무엇입니까? 카운트 값이 아닙니다.
JustinC

5
Java를 말할 때 Java 7부터 가독성을
Nick

2
이것들은 유효한 상수의 끔찍한 예입니다. 열거 형 이전에 만들어진 것을 제외하고는 열거 형이어야합니다.
Christoffer Hammarström

@ ChristofferHammarström 그것들은 실제로 열거 형 이전에 만들어졌으며 Java SDK의 SQL 패키지에서 ResultSet 클래스의 일부입니다.
Tulains Córdova

2
@ ChristofferHammarström 그들은 우리가 열거 형을 가지고 있기 때문에 나쁘지만 의미가 없습니다. 이러한 클래스를 만들 때 열거 형이 존재하지 않았으며 FETCH_FORWARD 및 FETCH_REVERSE와 같은 상호 배타적 옵션을 구별하기 위해 다른 값을 제공합니다. 가치는 중요하지 않으며 단지 그들이 다르다는 사실 만 있습니다.
Tulains Córdova

8

미국 또는 유럽 억?

(또는 기술적 인 관점에서 볼 때, 단기 또는 장기 규모의 10 억-하나는 1 억, 다른 하나는 1 억입니다).

이 혼동이 주어지면 예라고 대답합니다. 한 번 정의하고 유지하는 것이 합리적입니다. 마찬가지로 정의에 동의 해야하는 상수에 적용하십시오-한 번 정의하십시오.


17
"미국 또는 유럽 억? - "뭐? 나도 몰라! 아 !!!!"
Tesserex

영국에서는 최소한 90 억 년을 채택한 지 오래되었습니다.
Jack Aidley

1
@Tesserex-글쎄, 당신은 당신이 왕일 때 이러한 것들을 알아야합니다.
gbjbaanb

5

하지 말아야 할 이유

첫째, 여기에 밑줄을 쓰거나 시뮬레이션을 위해 시뮬레이션을 사용하지 않는 이유가 있습니다. 코드에서 상수를 찾기가 더 어려워집니다. 일부 프로그램이 작동 중 어딘가에 일부 매개 변수에 대해 하드 코드 된 값 1500000을 표시한다고 가정하십시오. 프로그램의 소스 코드에서 이것이 실제로 발생하는 위치를 알고 싶습니다. 그래서 코드를 grep하고 1500000아무것도 찾지 못했습니다. 왜? 16 진수 일 수 있습니다 (그러나 왜 둥근 십진수인지). 나에게 알지 못하는 상수는 실제로로 쓰여집니다 1_500_000. 정규식이 필요했습니다 1_?500_?000.

댓글의 안내 문자

한 가지 종류의 시각 보조 도구를 사용할 수 없거나 위와 같은 이유로 사용하지 않으려 고한다고해서 텍스트 파일의 두 가지 차원을 활용하여 대체 시각 보조 도구를 만들 수 없다는 의미는 아닙니다.

foo = bar / 1000000000;
//           --^--^--^  

이를 통해 우리는 3 개의 0으로 구성된 3 개의 그룹이 있음을 쉽게 확신 할 수 있습니다. 그러나 여전히 소스 코드를 grep하여 1000000000찾을 수 있습니다.

구문 채색

프로그래밍 가능한 구문 색상이있는 텍스트 편집기를 사용하면 가독성을 높이기 위해 숫자를 상수로 그룹화하여 색상을 번갈아 표시 할 수 있습니다. 우리는 코드에서 아무것도 할 필요가 없습니다.

전처리 : C, C ++, 목표 C

자릿수 사이에 쉼표를 원한다면 C와 C ++에서 사전 처리를 사용할 수 있습니다.

/* Four digit base TH-ousand constant macro */
/* Condensed using Horner's rule */
#define TH(A,B,C,D) ((((((A) * 1000) + (B)) * 1000) + (C)) * 1000 + D)

tv_sec = nanoseconds / TH(1,000,000,000)

와 같은 숫자에서 작동합니다 TH(1,234,567,890).

TH와 유사한 매크로는 산술보다는 토큰 붙여 넣기로 작동 할 수 있습니다. C 프리 프로세서에서 2 진 ##연산자 ( "토큰 붙여 넣기")를 매크로 본문에서 두 피연산자를 단일 토큰에 붙여 넣기 위해 사용할 수 있습니다. 피연산자 중 하나 또는 둘 다가 매크로 인수 일 수 있습니다. 여기서 단점은 (우리에게 위험을 초래할 수 있음) 결과 catenation이 유효한 토큰이 아닌 경우 동작이 정의되지 않는다는 것입니다.

#define TOK4(A, B, C, D) A ## B ## C ## D

지금

TOK4(1,000,000,000)       /* produces the single token 1000000000 */
TOK4(1,123,000,000.0E+2)  /* produces the single token 1123000000.0E+2 */
TOK4(pr,in,t,f)           /* produces the token printf */
TOK4(#,*,a,b)             /* undefined behavior, #*ab is not valid token syntax */

식별자를 붙여넣고 결과를 사용하여 전역 변수와 함수의 이름을 지정하는 C 프로그램은 존재하며 GNU id-utils 및 ctags와 같은 도구에는 영향을 미치지 않기 때문에 작업하기가 끔찍합니다.


2
내가 본 전 처리기의 최고의 남용 중 하나에 +1. 그래도 NSEC_PER_SEC 또는 프로덕션 환경에서 계속 사용합니다.
Victor

전 처리기 학대를위한 거의 -1 :)
CVn

3

예, 그것은 합리적인 생각처럼 들립니다. 일대일 DIGIT 오류는 악명 높은 일대일 오류보다 훨씬 나쁩니다. 하지만 다른 사람 (향후의 자기 자신 포함)이 코드를 읽는 데 혼란을 줄 수 있습니다.

NANOSEC_PER_SEC와 같은 더 설명적인 이름은 시간에 사용되는 곳에 명확성을 더할 것이므로 좋을 것 같습니다. 그러나 시간 이외의 상황에서 사용하는 것은 의미가 없으며 모든 상황에 대해 별도의 1,000,000,000을 만드는 것은 비현실적입니다.

처음에 보이는 것처럼 바보처럼하고 싶은 것은 '분할'입니다. NANO_PER는 언어 독립적 일뿐 아니라 (미국과 유럽에서는 10 ^ 9) 상황에 독립적이며 (단위 제한 없음) 입력하고 읽기 쉽습니다.


이 게시물은 읽기 어렵습니다 (텍스트의 벽). 더 나은 형태로 편집 하시겠습니까 ?
gnat

3

일반적으로 단위 변환에 스칼라 상수를 사용하는 것은 좋지 않으며, 이러한 일에 대해 상수를 만들면 너무 많은 곳에서 변환을 수행하고 있습니다.

한 단위의 수량 (예 : 10 초)이 있고 다른 단위 (예 : 나노초)로 변환하려는 경우 이 시간은 정확하게 언어 단위 시스템을 사용하여 원하는대로 단위를 실제로 조정할 수있는 시간입니다.

함수가 Nanoseconds매개 변수를 사용하도록하고 해당 클래스 Seconds에서 Minutes, 또는 무엇을 위해 변환 연산자 및 / 또는 생성자를 제공 하십시오. 당신의 곳이다 const int하거나 #define또는 1e9다른 답변에서 볼이 속한다.

이렇게하면 모호한 단위의 변수가 코드 주위에 떠 다니는 것을 피할 수 있습니다. 그리고 잘못된 곱셈 / 나눗셈이 적용되었거나 이미 적용된 또는 버그의 양이 실제로 시간 대신 거리가 아니었던 버그의 전체 엉킴을 방지합니다 ...

또한 이러한 클래스에서는 일반 스칼라를 사용하여 생성하고 정적 "MakeSeconds (int)"를 사용하거나 불투명 한 숫자를 느슨하게 사용하지 않는 것이 좋습니다.

더 구체적으로 C ++에서 Boost.Chrono를 확인하십시오 .


1
+ 최소한, 자주 정렬되는 시간대와 마찬가지로 기본 스케일링 또는 오프셋 계수가있는 공통 유형을 사용하십시오.
JustinC

1

나는 개인적으로 상수가 아닌 한 상수를 만드는 것이 좋지 않다고 생각합니다. 여러 위치에 있고 수정 / 테스트를 위해 파일 상단에 정의 된 것이 절대적으로 유용 할 것입니다.

입력하기가 어색하기 때문에? 그럼 아닙니다.

개인적으로 상수가 정의 된 다른 사람의 코드를 얻은 경우 일반적 으로이 코드의 중요한 측면이라고 생각합니다. 예를 들어 TCP는 활성 타이머를 유지하며 허용되는 최대 연결 수입니다. 디버깅해야한다면 왜 / 어디에서 사용되는지 알아 내려고 노력할 필요가 없습니다.


나는 농담을 얻지 만 은행 프로그래머가 모든 숫자를 일정하게 유지해야한다면 소프트웨어를 전송할 수있는 것은 거대하고 관리하기가 어렵고 느릴 것입니다. 나는 그것이 어떨지 상상할 수 있었다. 돈을 송금하는데 3 일이 걸린다고 들었다고 상상 해보자 .... OH MY GOD, ITHAT !!!
Simon McLoughlin 17 년

은행에서 송금하는 데 3 일이 걸립니다 :(
Reactgular

1
@MathewFoscarini 은행가는 Excel을 사용합니다. 프로그래머가 필요 없습니다.)
Mateusz

@Simon 언어와 컴파일러에 따라 오버 헤드가 거의없이 상수를 코드에 최적화해야합니다. 요점을 이해하지만 매직 번호 대신 이름을 사용하면 코드 가독성을 향상시키는 데 상수를 사용할 수 있습니다.
Steven

읽기 어색한 것은 입력하기 어색한 것보다 훨씬 더 큰 문제입니다.
Alb

0

질문 제목에 "1000000000"대신 "10 억"을 쓴 이유를 생각할 때 답이 예인 이유를 알게됩니다.


0

큰 리터럴에 상수를 만들지 마십시오. 그러한 리터럴마다 상수가 필요합니다. 제 의견으로는 완전한 농담입니다. 구문 강조와 같은 것들을 사용하지 않고 리터럴을 더 명확하게 만들어야하는 경우 인생을 더 쉽게 만들 수있는 함수 나 매크로를 만들 수는 없습니다.

#define SPLIT3(x, y, z) x##y##z

int largeNumber1 = SPLIT3(123,456,789);
int largeNumber2 = 123456789;

0

나는 이것을 할 것이다 :

const int Million = 1000 * 1000;
const int Billion = 1000 * Million;

또는

const int SciMega = 1000 * 1000; const int SciGiga = 1000 * SciMega;

초당 나노초 수와 관련하여 나노는 기가의 "역"입니다.

Kilo  Mega  Giga   etc.
10^3  10^6  10^9
Milli Micro Nano   etc.
10^-3 10^-6 10^-9

과학적으로, 컴퓨터 에서처럼 킬로, 메가, 기가 등의 의미는 다릅니다. 1024 (2 ^ 10), 1024 * 1024 (2 ^ 20) 등 2 메가 바이트는 2,000,000 바이트가 아닙니다. .

UPDATE Commenter는 2의 디지털 지수에 대해 특별한 용어가 존재한다고 지적했다 : http://en.wikipedia.org/wiki/Mebibyte


"2 메가 바이트는 2,000,000 바이트가 아닙니다." 원하는 회전 플래터 하드 디스크 제조업체에 문의하십시오. (downvoter 아님, btw.)
CVn

@ michaelkjorling 이것은 비즈니스 윤리 나 마케팅 문제가 아닌 프로그래밍 문제입니다. 하드 드라이브에 대해서는 동의하지만 다른 주제입니다. 그리고 다운 투표에 대해 찬성!
Mr. TA

1
실제로 2 메가 바이트는 2,000,000 바이트입니다. 2 Mebibytes는 2,097,152 바이트입니다. 참조 en.wikipedia.org/wiki/Mebibyte
vy32

@ vy32 감사합니다, 전에는 들어 본 적이 없습니다. 그것을 반영하기 위해 내 대답을 업데이트 할 것입니다.
Mr. TA

@ Mr.TA, 문제 없습니다! 우리는 컴퓨터 과학이 SI 단위를 준수하도록 열심히 노력하고 있습니다! 동아리에 가입하다.
vy32
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.