OverflowException仅在VB.net中,而不在C#中

时间:2016-03-30 14:01:51

标签: c# vb.net

出于自学目的,我试图找到一种方法来自己创建一个高度图。 我google了一下,发现了一个创建伪随机数的函数。

    public static float Noise(int x)
    {
        x = (x << 13) ^ x;

        return (1f - ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7FFFFFFF) / 1073741824.0f);
    }

由于我选择的语言是VB.net,我将此功能翻译为:

Private Function Noise(ByVal x As Integer) As Double
    x = (x << 13) Xor x

    Return (1.0R - ((x * (x * x * 15731.0R + 789221.0R) + 1376312589.0R) And &H7FFFFFFF) / 1073741824.0R)
End Function

如果我使用C#版本,我会得到x值从1到100的结果。如果我使用VB.net版本,我得到x <6的值,但x = 6的值为OverFlowException。当我拆开这个函数的部分时,我发现溢出的部分是

(x * x * 15731.0R)

所以,我的第一个问题是:为什么我在VB.net中获得OverflowException而在C#中没有?{如果中间结果对于包含变量而言太大,那么无论我使用何种语言,它都应该太大。

我的第二个问题是:我还能做些什么才能让它在VB.net中运行?

感谢您的回答。

2 个答案:

答案 0 :(得分:10)

  

为什么我在VB.net中获得了OverflowException而在C#中没有?

因为VB项目默认检查溢出,而C#没有。如果要将项目设置为检查溢出或将代码放在checked{ }块中,您会在C#中看到相同的异常:

public static float Noise(int x)
{
    x = (x << 13) ^ x;
    checked{
        return (1f - ((x * (x * x * 15731) + 1376312589) & 0x7FFFFFFF) / 1073741824.0f);
    }
}
  

我还能做些什么才能让它在VB.net中运行?

我怀疑它对C#“有用”。由于它无声地溢出,你可能会得到不正确的结果。

但是,您可以通过将x转换为double来阻止溢出:

Private Function Noise(ByVal x As Integer) As Double
    x = (x << 13) Xor x

    Dim y As Double = x

    Return (1.0R - ((y * (y * y * 15731.0R) + 1376312589.0R) And &H7FFFFFFF) / 1073741824.0R)
End Function

您还可以打开VB项目的“删除整数溢出检查”属性,但这是项目范围设置。 VB目前没有办法关闭像C#那样的特定代码行的溢出检查。

无论你做什么,我都会彻底测试它,因为你正在计算一个浮点值,对它进行位掩码(And &H7FFFFFFF)然后除以另一个浮点值。混合整数和浮点数学可能非常棘手。

另请注意,您的两个代码段并不等效。您的C#函数返回float,而VB返回Double。你在VB中使用浮点文字但在C#中使用整数文字。它似乎不是一个很大的区别,但它可以意外地改变数学。

答案 1 :(得分:0)

就像D Stanley指出的那样,VB.net中OverFlowException的原因是VB.net自动对整数运算进行溢出检查,而C#则不行。

如果其他人有兴趣让它在VB.net中运行,您可以执行以下操作:

将此结构添加到您的项目

<StructLayout(LayoutKind.Explicit)>
Public Structure LongToIntegerNoOverflow
    <FieldOffset(0)>
    Public LongValue As Long
    <FieldOffset(0)>
    Public IntValue As Integer
End Structure

并将Noise功能更改为

Private Function Noise(ByVal x As Integer) As Single
    Dim x1 As Long
    Dim x2 As LongToIntegerNoOverflow
    Dim x3 As LongToIntegerNoOverflow
    Dim x4 As Long

    x1 = (x << 13) Xor x

    x2.LongValue = x1 * x1 * 15731 + 789221
    x3.LongValue = x1 * x2.IntValue + 1376312589

    x4 = x3.IntValue And &H7FFFFFFF

    Return (1.0R - x4 / 1073741824.0R)
End Function

经过这些更改后,我在VB.net和C#中得到了相同的结果。