NA_real_ 和 NaN 之间的区别
Difference between NA_real_ and NaN
当我使用.Internal(inspect())
到NA_real_
和NaN
时,它returns,
> .Internal(inspect(NA_real_))
@0x000001e79724d0e0 14 REALSXP g0c1 [REF(2)] (len=1, tl=0) nan
> .Internal(inspect(NaN))
@0x000001e797264a88 14 REALSXP g0c1 [REF(2)] (len=1, tl=0) nan
好像他们唯一的区别就是内存地址。
但是,当我将 NA_real_
和 NaN
强制转换为字符时,它 returns,
> as.character(c(NaN, NA_real_))
[1] "NaN" NA
我理解应该 return 以上结果,因为 NaN
不能是字符,它将被强制转换为 "NaN"
但 NA_real
将被强制转换为NA_character_
。但考虑到他们的直觉是一样的,R return 怎么会有不同的结果呢?
提前感谢您的任何建议!
NA
是一个统计 或数据完整性 概念:“缺失值”的概念。例如,如果您的数据来自填写表格的人,则错误条目或缺失条目将被视为 NA
.
NaN
是一个 numerical 或 computational 概念:“不是数字”的东西。例如0/0是NAN
,因为这个计算的结果是未定义的(但注意1/0是Inf
,或者无穷大,同样-1/0是-Inf
)。
R 在内部处理这些概念的方式不是您应该关心的事情。
嗯。首先,请记住 NA
是一个 R 概念,在 C 中没有等价物。因此,NA
需要在 C 中以不同的方式表示。事实上 .Internal(inspect())
不会这种区别并不意味着其他地方没有。事实上,.Internal(inspect())
使用 Rprintf
来打印值的内部双精度浮点表示。而且,实际上,R NA 被编码为 C 浮点类型中的 NaN 值。
其次,您观察到“它们唯一的区别是内存地址”。 - 所以呢?至少概念上, 不同的内存地址完全足以区分 NA 和 NaN,不需要更多。
但事实上R通过不同的途径来区分这些值。这是可能的,因为 IEEE 754 double precision floating point format has multiple different representations of NaN,并且 R 为 NAs 保留了一个特定的:
static double R_ValueOfNA(void)
{
/* The gcc shipping with Fedora 9 gets this wrong without
* the volatile declaration. Thanks to Marc Schwartz. */
volatile ieee_double x;
x.word[hw] = 0x7ff00000;
x.word[lw] = 1954;
return x.value;
}
和:
/* is a value known to be a NaN also an R NA? */
int attribute_hidden R_NaN_is_R_NA(double x)
{
ieee_double y;
y.value = x;
return (y.word[lw] == 1954);
}
int R_IsNA(double x)
{
return isnan(x) && R_NaN_is_R_NA(x);
}
int R_IsNaN(double x)
{
return isnan(x) && ! R_NaN_is_R_NA(x);
}
(src/main/arithmetic.c
)
当我使用.Internal(inspect())
到NA_real_
和NaN
时,它returns,
> .Internal(inspect(NA_real_))
@0x000001e79724d0e0 14 REALSXP g0c1 [REF(2)] (len=1, tl=0) nan
> .Internal(inspect(NaN))
@0x000001e797264a88 14 REALSXP g0c1 [REF(2)] (len=1, tl=0) nan
好像他们唯一的区别就是内存地址。
但是,当我将 NA_real_
和 NaN
强制转换为字符时,它 returns,
> as.character(c(NaN, NA_real_))
[1] "NaN" NA
我理解应该 return 以上结果,因为 NaN
不能是字符,它将被强制转换为 "NaN"
但 NA_real
将被强制转换为NA_character_
。但考虑到他们的直觉是一样的,R return 怎么会有不同的结果呢?
提前感谢您的任何建议!
NA
是一个统计 或数据完整性 概念:“缺失值”的概念。例如,如果您的数据来自填写表格的人,则错误条目或缺失条目将被视为 NA
.
NaN
是一个 numerical 或 computational 概念:“不是数字”的东西。例如0/0是NAN
,因为这个计算的结果是未定义的(但注意1/0是Inf
,或者无穷大,同样-1/0是-Inf
)。
R 在内部处理这些概念的方式不是您应该关心的事情。
嗯。首先,请记住 NA
是一个 R 概念,在 C 中没有等价物。因此,NA
需要在 C 中以不同的方式表示。事实上 .Internal(inspect())
不会这种区别并不意味着其他地方没有。事实上,.Internal(inspect())
使用 Rprintf
来打印值的内部双精度浮点表示。而且,实际上,R NA 被编码为 C 浮点类型中的 NaN 值。
其次,您观察到“它们唯一的区别是内存地址”。 - 所以呢?至少概念上, 不同的内存地址完全足以区分 NA 和 NaN,不需要更多。
但事实上R通过不同的途径来区分这些值。这是可能的,因为 IEEE 754 double precision floating point format has multiple different representations of NaN,并且 R 为 NAs 保留了一个特定的:
static double R_ValueOfNA(void)
{
/* The gcc shipping with Fedora 9 gets this wrong without
* the volatile declaration. Thanks to Marc Schwartz. */
volatile ieee_double x;
x.word[hw] = 0x7ff00000;
x.word[lw] = 1954;
return x.value;
}
和:
/* is a value known to be a NaN also an R NA? */
int attribute_hidden R_NaN_is_R_NA(double x)
{
ieee_double y;
y.value = x;
return (y.word[lw] == 1954);
}
int R_IsNA(double x)
{
return isnan(x) && R_NaN_is_R_NA(x);
}
int R_IsNaN(double x)
{
return isnan(x) && ! R_NaN_is_R_NA(x);
}
(src/main/arithmetic.c
)