d中nan接下来
可这样:
static assert(float() is float.nan);
这仅适合float.init,但如果操作它并返回nan,那不一定是真的,因为nans有几种位模式.
static assert(float() is real.nan);
static assert(double() is real.nan);
static assert(real() is real.nan);
同小类型比较,会提升.
除了T.nan还有其他类型NaN吗?如何生成它们?
0F/0F is float.nan是真.
与大小无关,而是nan们可以不同形式出现.考虑:
void main() {
float f = 7.0;
f /= 0;
import core.stdc.stdio;
printf("%d\n", *cast(int*)&f);
if(f is float.init)
printf("nan\n");
}
该与float.init不一样,
f = 1.0;
f /= 0;
assert(f is f.infinity);
//
float f = 0;
f /= 0;
assert(f is f.nan); //失败了.
这样来零初化:
template ZeroInit(T)
{
union U
{
byte[T.sizeof] a;
T zeroed;
}
enum ZeroInit = U().zeroed;
}
struct S
{
float f;
float[2] a;
}
void main()
{
S s = ZeroInit!S;
assert(s.f == 0);
assert(s.a == [0,0]);
}
int.min并不是真正的NaN.
但它应该是!int.min是臭名昭著的虚假值.甚至不能在它上面使用abs():它要么给你不同类型,要么返回垃圾.
我在每个程序中做的第一件事就是精确定义:byte/short/int/long的别名,置T.min+1为实际最小值.
不必自己写;可用std.checkedint的Checked!(int,WithNaN),在此
可以这样,用std.typecons.Typefef:
import std;
alias Distance = Typedef!(double, 0.0, "distance");
alias Temperature = Typedef!(double, 0.0, "temperature");
void main()
{
Temperature t;
Distance d;
d += 4.5;
// t = d; // 不编译
}
但是,可能会在中间结果中丢失类型信息:
t = 0.5 + d;//结果为双精
包含NaN和无穷大等值理由:重点是简化错误处理,并允许延迟处理错误.
alias this是隐式转换工具.
个人喜欢D的做法.一旦你知道浮点有个"无"的方便初化值,同样原因null是指针和类引用的方便初化值.但如果我不知道NaN,这会很烦人.最大弱点是它违背了C,C++和C#(等其他语言)做法,很容易让人感到惊讶.
背后重要理念是D总是用"空"值作为初化值(如果有的话).
另一方面,程序员可显式初化变量为float.nan.
我在每个程序中都包含它,且从不使用其他有符号整数(正值用于位操作,而不是计算).checkedint应只是int类型,而不是模块.
浙公网安备 33010602011771号