1,000,000,000をCで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 2016年

54
... 2時間のためにあるの通知にその簡単な.. * 60 * 60 2:それは特にのような期間に使用
Idali

53
1,000,000,000は有効な構文ではないようです
paparazzo

15
ちなみに、現代のプログラミング言語には、たとえばSwiftのように、同じものを書く別の方法があります1_000_000_000。ただし、時定数を使用すると、これはさらに困難になります。30 * 60を書くよりも(30秒で30分)の方が読みやすくなります1800。実際には、ユニットを記述できる言語があります。たとえばmeters、悪い割り当てから身を守ることができます。
サルタン

29
^XORであり、指数演算子やべき演算子ではありません。
3Dave

回答:


200

定数を乗法的に宣言する理由の1つは、読みやすさを向上させることですが、実行時のパフォーマンスには影響しません。また、作家が数について乗法的に考えていたことを示します。

このことを考慮:

double memoryBytes = 1024 * 1024 * 1024;

それは明らかにより良いです:

double memoryBytes = 1073741824;

後者は一見すると1024の3乗です。

Amin Negm-Awadが述べたように、^演算子はバイナリXORです。多くの言語には、組み込みのコンパイル時の指数演算子がないため、乗算が行われます。


13
また、べき乗演算子がある言語では、必ずしも「^」である必要はありません。たとえばFortranでは、「**」です。
jamesqf 2016年

4
:あなたはまた、@chuxから以下の回答に与えられた重要な警告を指すリンク、含まれている必要がありstackoverflow.com/a/40637622/1841533を(OPは、この「RIGH手に非常に敏感である「c」を、タグ付けされた特にとして、副演算はすべての項がより小さな型に制限されているように見えるため、乗算がオーバーフローする可能性があります。 securecoding.cert.org/confluence/display/c/…は、一般的なケースでそれらを回避するのに役立ちますか?
Olivier Dulac 2016年

4
また、計算はコンパイル時に行われることにも注意してください。C標準では、言語のさまざまな機能のコンパイル時に定数式を計算できるように実装する必要があり、この例のように定数式が使用されている場合はtrueであると安全に想定できます。
2016年

13
メモリ量を2倍に保存しますか?これは潜在的なエラーの原因のようです。
JAB、

7
@supercat私はそれを知っていますが、doubleを使用することで、たとえば、メモリ範囲の一部が必要な場合、分割しxてサブ範囲のサイズを取得する場合があります...そして突然、分数になりますバイト、これを補うために追加のロジックが必要になる場合があります。
JAB

73

なんで1000^3

の結果1000^3は1003 ^です。ビットXOR演算子です。

Q自体は扱っていませんが、説明を追加します。質問者の例のように常に評価するx^yわけではありませx+y。すべてのビットをxorする必要があります。例の場合:

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 ++ / Objective-Cの等の計算機で通常の手段Xツー-Yパワーオペレータ手段XOR。
タマシュZahola

5
バー、1000と3のビットはオーバーラップしません。これはとても間違っているようです。
Yakk-Adam Nevraumont 2016年

19
ビットは重複しています。しかし、1ではありません。:-]
Amin Negm-Awad 2016

6
@ヤク:確かに、それはとても間違って見えます!...多くの人が "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 2016年

2
A doubleは、2 ^ 53≈9e15までのすべての整数を正確に表すことができます。
Edgar Bonet、2016年

3
@EdgarBonet binary64が約9e15までの整数を表すことができることは真です。しかし、Cはdoublebinary64の使用を指定していませんが、それは非常に一般的に使用されています。C仕様によれば、1e9までの値は正確に表現できます。仕様に従ってコーディングするか、一般的な手法に依存するかによって異なります。
chux-モニカを2016年

4
@Patrick 10001000000000000は両方とも整数定数です。それぞれ独立してintlongまたはから選択されたタイプがありlong longます。コンパイラーは、整数定数が適合する3の最初のタイプを使用します。 それぞれとして数学1000 * 1000 * 1000 * 1000で行わintれます1000の中でint。製品は32ビットでオーバーフローしますint1000000000000 確かにlong long(またはおそらくより狭い)-オーバーフローなしとして表現できます。ターゲットのタイプは、long long Durationこの「==決定の右側」には影響しません。
chux-モニカを2016年

2
乗算の最初に幅の広いタイプを配置することが重要です。16ビットintlong x = 1000 * 1000 * 1000L;は、オーバーフローしますが、 オーバーフローしlong x = 1000L * 1000 * 1000;ません。
ex nihilo 2017

51

読みやすさのため。

ゼロ(1 000 000 000または1,000,000,000)の間にコンマとスペースを配置すると構文エラーが発生1000000000し、コード内にあるとゼロの数が正確にわかりにくくなります。

1000*1000*1000私たちの目はチャンクをより簡単に処理できるため、これは10 ^ 9であることが明らかになります。また、コンパイラが定数に置き換えるため、実行時のコストもかかりません1000000000


5
ちなみに、最近学んだ桁区切りの概念があります。Javaはしばらくの間それを持っています、そしてC#7.0はそれを得るかもしれません。私はすべての言語にこの素晴らしい機能があることを望みます。:)
iheartcsharp 2016年

1
使用するコンテキストによっては、1,000,000,000構文エラーは発生しませんが、それは単に別のことを意味します。例えばCMTimeMakeWithSeconds( newDurationSeconds, 1,000,000,000 )
ロス・リッジ

2
@ JMS10 C#は、VS15プレビューバージョンをインストールした場合、すでにそれを持っています。次のように記述できます1_000_000_000
user1306322

2
Python _も区切り文字として使用されています:)
Wayne Werner、

2
C ++は最近'C ++ 14でセパレーターを取得したので、を使用できます1'000'000'000。(これは1,000,000,000、カンマ演算子または4つの異なるパラメーターとして誤って解釈される可能性が_1_000_000_000あり、有効な(ただし、おそらく悪い)変数名であるために選択されました。)
ジャスティンタイム-モニカを

27

読みやすさのため。比較のために、Javaは_読みやすさを改善するために数をサポートしています(Derek Fosterの提案返答としてStephen Colebourneによって最初に提案されました Project Coin / JSR 334のバイナリリテラル)。1_000_000_000ここに書きます。

おおまかな年代順に、最も古いサポートから新しいサポートへ:

これは、言語がサポートすべきであることを理解するための比較的新しい機能です(Perlもあります)。chux @の優れた答えのように、これ1000*1000...は部分的な解決策ですが、最終的な結果が大きい型であっても、乗算のオーバーフローによるバグにプログラマーを解放します。


Swiftなど、多くの最新のプログラミング言語は同じです。新しいものはありません。
サルタン

AFAIK、これはPerlから来ています。PL / Mは同じ目的に$を使用しました。例:0100 $ 0010B
ninjalj

1
しかし、それかなり新しいです。Java機能はおそらく5年前のものです。この構文をサポートする他のほとんどの言語はかなり新しいものです-Swift自体はほんの数年前のものです。Pythonは、まだリリースされていない3.6のサポートを追加します。
johncip 2016年

2
Adaは33年間整数リテラルの下線をサポートしてきました。
ピーター-2016年

1
@djechlin:私は、大まかに年代順に、より多くの情報を自由に追加しました。私は以前、プロジェクトコインのスレッドから判断すると、誤解されていました。StephenColebourneはおそらく、FandomやRubyの整数リテラルにアンダースコアを使用するという考えを採用していました。RubyはおそらくPerlとPerlをAdaから採用しました。
ninjalj

7

を読んで、いくつかの関連付けを取得する方が簡単かもしれません 1,000,000,000フォーム。

技術的な面からは、直接の数と乗算の間に違いはないと思います。コンパイラはとにかくそれを一定の10進数として生成します。

Objective-Cについて話す1000^3と、そのようなpow(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ウィキペディアの記事を読んで言語を学ぶことはお勧めしません。
ピーター-モニカの復活2016

0

10進数のCで同様の効果を達成する別の方法は、リテラル浮動小数点表記を使用することです-精度を失うことなくdoubleが必要な数を表すことができる限り。

IEEE 754 64ビットdoubleは、2 ^ 53未満の負でない整数を問題なく表すことができます。通常、長いdouble(80または128ビット)は、それよりもさらに長くなる可能性があります。変換はコンパイル時に行われるため、実行時のオーバーヘッドはなく、予期しない精度の損失があり、適切なコンパイラーがある場合は、警告が表示される可能性があります。

long lots_of_secs = 1e9;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.