整数和浮点数字面量
本课程将介绍整数和浮点数字面量及其语法规则。
字面量
程序通过操作变量的值来完成任务。它们通过将这些值与函数和运算符结合来生成新值。
然而,有些值在程序执行过程中无需被修改,而是直接以原始形式出现在源代码中。例如,下面代码中的浮点数 0.75 和字符串 "Total price: " 并不是由程序计算得出的:
1discountedPrice = actualPrice * 0.75; 2totalPrice += count * discountedPrice; 3writeln("Total price: ", totalPrice);
这些直接写入源代码的值被称为 字面量。到目前为止,我们已经在程序中使用过字符串字面量。现在,我们将学习其他类型的字面量。
整数字面量
整数字面量可以用以下四种方式书写:
-
十进制系统,即我们日常生活中使用的系统
-
十六进制和二进制系统,更适合某些计算任务
-
八进制系统,在极少数情况下可能需要使用
为了提高代码可读性,可以在整数字面量的第一个数字之后任意位置插入 _ 字符。例如,可以使用 _ 将数字分组为三位一组,如 1_234_567。另一个例子是用 _ 分隔货币单位和分,如 199_99。这些下划线字符是可选的,编译器会忽略它们。
-
十进制系统:整数字面量使用十进制表示法,与通常的数字写法一致,例如 12、456 等。
在 D 语言中使用十进制书写字面量时,第一个数字不能是 0。其他编程语言中常使用前导零来表示八进制,因此 D 语言的这一限制有助于避免因这种容易忽略的差异而引发的错误。但单独的 0 是允许的:0 表示零。
-
十六进制系统:这些字面量以 0x 或 0X 开头,包含十六进制数字 "0123456789abcdef" 和 "ABCDEF",例如 0x12ab00fe。
-
八进制系统:这些字面量使用
std.conv模块提供的八进制模板,包含八进制数字 "01234567",例如 octal!576。 -
二进制系统:这些字面量以 0b 或 0B 开头,包含二进制数字 0 和 1,例如 0b01100011。
整数字面量的类型
就像程序中使用的每个变量都必须有类型一样,字面量也有特定的类型。字面量的类型不会显式地写成 int、double 等形式,而是由编译器根据字面量的值和语法自动推断。
虽然大多数情况下字面量的类型并不重要,但在某些情况下,其类型可能与所参与的表达式不匹配。此时,必须 显式 指定类型。
默认情况下,整数字面量的类型被推断为 int。如果该值超出了 int 的范围,编译器将采用以下逻辑决定其类型:
- 如果字面量的值无法放入
int,且是以十进制表示的,则其类型为long。 - 如果字面量的值无法放入
int,且不是以十进制表示的,则其类型为以下类型中第一个能容纳该值的类型:uint、long、ulong。
为了直观理解这一逻辑,我们来看下面这个利用 typeof 和 stringof 的程序:
1import std.stdio; 2 3void main() { 4 writeln("\n--- 这些是以十进制书写的 ---"); 5 6 // 能放入 int,所以类型是 int 7 writeln( 2_147_483_647, "\t\t", typeof(2_147_483_647).stringof); 8 9 // 无法放入 int 且为十进制,所以类型是 long 10 writeln( 2_147_483_648, "\t\t", typeof(2_147_483_648).stringof); 11 12 writeln("\n--- 这些不是以十进制书写的 ---"); 13 14 // 能放入 int,所以类型是 int 15 writeln( 0x7FFF_FFFF, "\t\t", typeof(0x7FFF_FFFF).stringof); 16 17 // 无法放入 int 且非十进制,所以类型是 uint 18 writeln( 0x8000_0000, "\t\t", typeof(0x8000_0000).stringof); 19 20 // 无法放入 uint 且非十进制,所以类型是 long 21 writeln( 0x1_0000_0000, "\t\t", typeof(0x1_0000_0000).stringof); 22 23 // 无法放入 long 且非十进制,所以类型是 ulong 24 writeln( 0x8000_0000_0000_0000, "\t", typeof(0x8000_0000_0000_0000).stringof); 25}
L 后缀
无论数值大小如何,只要字面量以 L 结尾(如 10L),其类型就是 long。
U 后缀
如果字面量以 U 结尾(如 10U),则其类型为 无符号类型,具体取决于字面量的值。小写字母 u 也可以使用。
浮点数字面量
浮点数字面量可以用十进制(如 1.234)或十六进制(如 0x9a.bc)表示。
-
十进制系统:可以在数字后附加
e或E来表示指数,含义为“乘以 10 的幂”。例如,3.4e5 表示“3.4 × 10⁵”,即 340000。在指数前加-表示“除以 10 的幂”。例如,7.8e-3 表示“7.8 除以 10³”。也可以在指数前加+,但效果等同于没有加号。例如,5.6e2 和 5.6e+2 是相同的。 -
十六进制系统:数值以 0x 或 0X 开头,小数点前后部分均使用十六进制数字表示。由于
e和E在此系统中是有效数字,因此指数使用p或P表示。另一个区别是,指数表示的是“2 的幂”而非“10 的幂”。例如,0xabc.defP4 中的 P4 表示“2 的 4 次方”。
浮点数字面量通常包含小数点,但如果指定了指数,小数点可以省略。例如,2e3 是一个浮点数字面量,值为 2000。小数点前的数值可以省略,若为零。例如,.25 是一个值为“四分之一”的字面量。
浮点数字面量也可以使用可选的 _ 字符,如 1_000.5。
浮点数字面量的类型
除非显式指定,浮点数字面量的类型默认为 double。f 和 F 后缀表示 float,L 后缀表示 real。例如,1.2 是 double 类型,3.4f 是 float 类型,5.6L 是 real 类型。
在下一课中,你将遇到一个与字面量使用相关的编程挑战。