为什么要在 C 中将 1,000,000,000 写为 1000*1000*1000?

Why write 1,000,000,000 as 1000*1000*1000 in C?

提问人:Duck 提问时间:11/16/2016 最后编辑:LaurelDuck 更新时间:2/5/2023 访问量:15918

问:

在 Apple 创建的代码中,有这样一行:

CMTimeMakeWithSeconds( newDurationSeconds, 1000*1000*1000 )

有什么理由表示为?1,000,000,0001000*1000*1000

为什么不呢?1000^3

objective-c c 整数 文字

评论

47赞 Iwillnotexist Idonotexist 11/16/2016
代码的清晰度和可读性。你不能把 或 ' 作为 C 语言中的分隔符,所以下一个最好的办法是从乘法中计算值。^ 是 C 中不相关的运算符 - 排他性 OR。
55赞 Idali 11/16/2016
它特别适用于持续时间:2*60*60 ..很容易注意到这是 2 小时。.
53赞 paparazzo 11/16/2016
首先,我怀疑 1,000,000,000 不是有效的语法
15赞 Sulthan 11/17/2016
顺便说一句,现代编程语言有另一种编写相同的方法,例如在 Swift 中。然而,对于时间常数,这更加困难。写起来(30 分钟,以秒为单位)比写起来更易读。实际上有一些语言可以让你写单位,例如,允许你保护自己免受不良作业的影响。1_000_000_00030 * 601800meters
30赞 3Dave 11/17/2016
^是异或,而不是指数或幂运算符。

答:

74赞 Amin Negm-Awad 11/16/2016 #1

为什么不呢?1000^3

的结果是 1003. 是位异或运算符。1000^3^

即使它不涉及 Q 本身,我也会添加一个澄清。 并不总是像提问者示例中那样评估 to。你必须xor每一点。在示例中:x^yx+y

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

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

评论

3赞 MD. 11/16/2016
先生,我不清楚 1003^3 是怎么做到的 1003。Google 和 Mac 计算器显示 1000^3 = 1,000,000,000。你能解释一下吗?
61赞 Tamás Zahola 11/16/2016
运算符表示 C/C++/目标 C 等中的异或。在计算器中,它通常表示 x 到 y 的幂。^
5赞 Yakk - Adam Nevraumont 11/17/2016
呸,1000 和 3 的位不重叠。这看起来很不对劲。
22赞 Amin Negm-Awad 11/17/2016
这些位确实重叠。但不是 1 的。:-]
6赞 Olivier Dulac 11/17/2016
@Yakk:确实,看起来太不对劲了!...我希望很多人不会认为“A^B”总是给出 A+B(但我担心有些人可能会......
7赞 Madars Vi 11/16/2016 #2

可能更易于阅读并获得与表单的一些关联。1,000,000,000

从技术方面来看,我想直接数或乘法之间没有区别。无论如何,编译器都会将其生成为常量十亿数。

如果你谈论 objective-c,那么将不起作用,因为 pow 没有这样的语法(它是 xor)。相反,可以使用函数。但在这种情况下,它不会是最优的,它将是一个运行时函数调用,而不是编译器生成的常量。1000^3pow()

204赞 Piotr Falkowski 11/16/2016 #3

以乘法方式声明常量的一个原因是提高可读性,同时不受运行时性能的影响。 此外,表明作者正在以乘法方式思考这个数字。

考虑一下:

double memoryBytes = 1024 * 1024 * 1024;

这显然比:

double memoryBytes = 1073741824;

因为后者乍一看不是 1024 的第三次方。

正如 Amin Negm-Awad 所提到的,运算符是二进制 。许多语言缺少内置的编译时幂运算符,因此需要乘法。^XOR

评论

14赞 jamesqf 11/17/2016
在有幂运算符的语言中,它不一定是“^”。例如,在 Fortran 中,它是“**”。
4赞 Olivier Dulac 11/17/2016
您还应该包含一个链接,指向重要的警告,在下面的答案中给出,来自 @chux : stackoverflow.com/a/40637622/1841533(特别是当 OP 标记为“c”时,它非常容易受到这种“righ-hand side 操作似乎将所有项限制为较小的类型,因此乘法可能会溢出”问题)。securecoding.cert.org/confluence/display/c/......可能有助于避免一般情况下的那些?
4赞 ouah 11/17/2016
我们还应该注意,计算是在编译时完成的。C 标准要求实现能够在编译时计算语言的各种功能的常量表达式,我们可以放心地假设当使用常量表达式时,如本例所示。
13赞 JAB 11/17/2016
将内存量存储为双倍?这似乎是一个潜在的错误来源。
7赞 JAB 11/17/2016
@supercat我知道这一点,但是通过使用 double,您可能会遇到这样的情况,例如,您想要内存范围的一部分,您可以除以得到子范围的大小......突然间,你有一个小数字节,这可能需要额外的逻辑来补偿。x
52赞 Tamás Zahola 11/16/2016 #4

为了可读性。

在零 ( 或 ) 之间放置逗号和空格会产生语法错误,并且代码中包含会使得很难确切地看到有多少个零。1 000 000 0001,000,000,0001000000000

1000*1000*1000很明显它是 10^9,因为我们的眼睛可以更容易地处理块。此外,没有运行时成本,因为编译器会将其替换为常量 .1000000000

评论

5赞 iheartcsharp 11/16/2016
仅供参考,我最近了解到一个数字分隔符的概念。Java 已经有一段时间了,C# 7.0 可能会得到它。我希望所有语言都能有这个令人眼花缭乱的功能。:)
1赞 Ross Ridge 11/17/2016
根据上下文使用不会产生语法错误,它只会意味着其他东西。例如1,000,000,000CMTimeMakeWithSeconds( newDurationSeconds, 1,000,000,000 )
2赞 user1306322 11/17/2016
@JMS10 C# 已经拥有它,如果你安装 VS15 预览版,可以写成1_000_000_000
2赞 Wayne Werner 11/17/2016
Python 作为分隔符也越来越:)_
2赞 Justin Time - Reinstate Monica 11/17/2016
C++最近在C++14中获得了分隔符,因此您可以使用.(之所以选择它,是因为可能会被误解为逗号运算符或 4 个不同的参数,并且是一个有效(但可能是错误的)变量名称。'1'000'000'0001,000,000,000_1_000_000_000
27赞 djechlin 11/16/2016 #5

为了可读性。为了进行比较,Java 支持数字以提高可读性(首先由 Stephen Colebourne 提出,作为对 Derek Foster 的 PROPOSAL: Binary Literals for Project Coin/JSR 334) 的回复。有人会写在这里。_1_000_000_000

大致按时间顺序,从最旧的支持到最新的支持:

对于语言来说,这是一个相对较新的功能,可以意识到它们应该支持(然后是Perl)。正如 chux@ 的出色回答一样,这是一个部分解决方案,但即使最终结果是一个大类型,程序员也会因乘法溢出而面临错误。1000*1000...

评论

0赞 Sulthan 11/17/2016
许多现代编程语言都有相同的,例如 Swift。没什么新鲜的。
0赞 ninjalj 11/17/2016
AFAIK,这来自Perl。PL/M 将 $ 用于相同的目的,例如:0100$0010B
1赞 johncip 11/17/2016
不过,这是相当新的。Java 功能可能已有 5 年的历史了。大多数支持这种语法的其他语言都是相当新的——Swift 本身只有几年的历史。Python 在尚未发布的 3.6 中添加了支持。
2赞 Peter - Reinstate Monica 11/17/2016
33 年来,Ada 一直支持整数文字中的下划线。
1赞 ninjalj 11/18/2016
@djechlin:我冒昧地添加了更多信息,大致按时间顺序排列。我之前弄错了,从 Project Coin 线程来看,Stephen Colebourne 可能从 Fandom 和/或 Ruby 中采用了整数字面量中的下划线的想法。Ruby 可能从 Perl 那里得到了这个想法,而 Perl 则从 Ada 那里得到了这个想法。
77赞 chux - Reinstate Monica 11/17/2016 #6

有理由不使用 .1000 * 1000 * 1000

使用 16 位 ,溢出。因此,使用会降低可移植性。int1000 * 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;

此外,代码可以简单地使用表示法来表示完全可以表示为 .当然,这导致知道是否可以准确表示整数值 - 对于大于 1e9 的值,这是值得关注的。(请参阅和)。edoubledoubleDBL_EPSILONDBL_DIG

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

评论

5赞 Olivier Dulac 11/17/2016
非常重要的一句话!securecoding.cert.org/confluence/display/c/......在很多情况下可能会有所帮助?
2赞 Edgar Bonet 11/17/2016
A 可以精确地表示 2^53 ≈ 9e15 以内的所有整数。double
5赞 chux - Reinstate Monica 11/17/2016
@EdgarBonet 没错,binary64 可以表示大约 9e15 的整数。但是 C 没有指定 binary64 的使用,尽管它非常常用。根据 C 规范,最多 1e9 左右的值是完全可表示的。这取决于你是想按照规范编写代码还是依赖常见做法。double
8赞 chux - Reinstate Monica 11/18/2016
@Patrick 和 都是整数常量。每个独立 具有从 或 中选择的类型。编译器使用整数常量适合的 3 种类型中的第一种类型。 是用数学完成的,因为每个 .产品溢出 32 位 . 当然可以表示为(或可能更窄)- 没有溢出。目标的类型不会影响这个“=的右侧”detemrination。10001000000000000intlonglong long1000 * 1000 * 1000 * 1000int1000intint1000000000000long longlong long Duration
4赞 ad absurdum 7/24/2017
在乘法中将较宽的类型放在首位很重要。使用 16 位 ,会溢出,而不会。intlong x = 1000 * 1000 * 1000L;long x = 1000L * 1000 * 1000;
4赞 Peter - Reinstate Monica 11/17/2016 #7

为了说明原因,请考虑以下测试程序:

$ 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赞 Peter - Reinstate Monica 12/3/2016
@pjvandehaar我不建议通过阅读维基百科文章来学习语言。
0赞 jschultz410 6/20/2017 #8

在 C 语言中实现十进制数类似效果的另一种方法是使用文字浮点表示法——只要双精度可以表示您想要的数字而不会损失任何精度。

IEEE 754 64 位双精度可以毫无问题地表示任何非负整数 <= 2^53。通常,长双精度(80 或 128 位)可以走得更远。转换将在编译时完成,因此没有运行时开销,如果出现意外的精度损失并且您有一个良好的编译器,您可能会收到警告。

long lots_of_secs = 1e9;