为什么NaN(不是数字)仅适用于双打?

时间:2009-06-12 11:59:44

标签: c# types

我有一个包含两个可以为空的十进制属性的业务类。第三个属性返回乘以其他两个属性的结果。如果两个可空类型的HasValue为真,那么我乘以并返回结果。如果其中一个或两个属性为null,我有一些返回值的选项:

  • 返回0
  • 抛出异常
  • 返回一个幻数(-1)
  • 返回小数? (编辑 - 见评论)

我认为我的一个选择是返回NaN,但我发现这只适用于double类型。这是为什么?

对于记录,在这种情况下返回0最有意义,除非有人有更好的建议,否则这就是我打算做的事情。

2 个答案:

答案 0 :(得分:38)

.NET中的积分类型使用二进制补码系统进行表示。虽然他们可以为特殊值保留一些位模式,但他们选择不这样做。 doublefloat使用完全不同的表示系统(IEEE 754),为NaN,+ Infinity,-Infinity保留一些特殊的位模式......

NaN和Infinity值对浮点运算更有意义的一个原因是运算可能会导致除零,不仅因为除数实际为零,而且因为它太小而无法用类型表示。结果,如果不是这种情况,你可能会有一些有效的计算神秘地抛出除零异常。对于int类型,这不会发生,因为它们是精确的并且没有精度错误。

decimal旨在用于“真实世界”的十进制浮点数。它很少需要doublefloat计算的计算。 NaN表达真实世界号码的内容是什么?

仅仅留下它背后的原因,它就是它,我们无能为力,所以最好的方法是使用可空类型(它们旨在帮助完全解决这种情况)。这是正确的方法来解决这个问题。如果您不想这样做(并且异常没有意义),您应该使用幻数解决方案。如果您选择这样做,请确保它不在有效结果域之内。

编辑(关于十进制的非常常见的误解):

As also noted by MSDNdecimal不是固定点。它是一个浮点数:

  

十进制数是一个浮点值,由一个符号,一个数值组成,其中值中的每个数字的范围为0到9,以及一个缩放因子,指示分隔积分的浮点小数点的位置和数值的小数部分。

答案 1 :(得分:-6)

解决NAN&无限使用此

Initialize engine version: 5.4.2f2 (b7e030c65c9b)
-------- Shader compilation failed
#version 100
#extension GL_EXT_frag_depth : enable
precision highp float;
uniform highp vec4 _ProjectionParams;
uniform highp vec4 _ZBufferParams;
uniform highp mat4 unity_CameraToWorld;
uniform highp mat4 _NonJitteredVP;
uniform highp mat4 _PreviousVP;
uniform highp sampler2D _CameraDepthTexture;
varying highp vec2 xlv_TEXCOORD0;
varying highp vec3 xlv_TEXCOORD1;
void main ()
{
    highp vec4 tmpvar_1;
    tmpvar_1 = texture2D (_CameraDepthTexture, xlv_TEXCOORD0);
    mediump vec2 tmpvar_2;
    highp vec4 tmpvar_3;
    tmpvar_3.w = 1.0;
    tmpvar_3.xyz = ((xlv_TEXCOORD1 * (_ProjectionParams.z / xlv_TEXCOORD1.z)) * (1.0/((
                   (_ZBufferParams.x * tmpvar_1.x)
                   + _ZBufferParams.y))));

    highp vec4 tmpvar_4;
    tmpvar_4 = (unity_CameraToWorld * tmpvar_3);

    highp vec4 tmpvar_5;
    tmpvar_5 = (_PreviousVP * tmpvar_4);

    highp vec4 tmpvar_6;
    tmpvar_6 = (_NonJitteredVP * tmpvar_4);

    highp vec2 tmpvar_7;
    tmpvar_7 = (((tmpvar_5.xy / tmpvar_5.w) + 1.0) / 2.0);

    highp vec2 tmpvar_8;
    tmpvar_8 = (((tmpvar_6.xy / tmpvar_6.w) + 1.0) / 2.0);
    tmpvar_2 = (tmpvar_8 - tmpvar_7);

    mediump vec4 tmpvar_9;
    tmpvar_9.zw = vec2(0.0, 1.0);
    tmpvar_9.xy = tmpvar_2;
    gl_FragDepthEXT = tmpvar_1.x;
    gl_FragData[0] = tmpvar_9;
}