小心VB.NET中的除运算符/和\

2024-05-04 20:08
文章标签 小心 运算符 net vb

本文主要是介绍小心VB.NET中的除运算符/和\,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载于:http://www.cnblogs.com/freshman0216/archive/2008/08/27/1276991.html

 VB.NET中除运算符有两种,普通除"/"和整数除"\",如果我们写程序时不注意两者的区别,很容易造成潜在的错误,这种错误很隐蔽,不容易被发现。而且VB.NET中类型转换和C#差别很大,应该引起我们足够的重视,这些看似微不足道的细节却直接关系都我们代码的健壮性。

      1.问题的引出

      下面是开发中遇到问题代码的简化部分,输入大部分数据都没问题,但当输入数字为18时会抛出异常“System.ArgumentException: 偏移量和长度超出数组的界限,于从索引到源集合结尾处的元素数量。在 System.Collections.ArrayList.GetRange(Int32 index, Int32 count)”。是什么原因使ArrayList集合越界呢?这和VB.NET中的除运算符有什么关系呢?当我们理解了VB.NET中两种除的区别以及类型转换(Double—>Integer)的实质后,问题的答案也就不言自明了。

 Sub Main()Console.WriteLine("请输入一个整数:")F1(Console.ReadLine())Console.ReadLine()End SubPublic Sub F1(ByVal times As Integer)Dim list As ArrayList = New ArrayList()'填充数据For i As Integer = 0 To 29list.Add(i)Next'把集合list中元素分成times份进行处理Dim oneTimeNum As Integer = list.Count / timesFor i As Integer = 0 To times - 1Dim length As Integer = oneTimeNumIf i = times - 1 Then'最后一次循环取集合中所有剩余数据length = list.Count - oneTimeNum * iEnd If'实际中这里是启动线程处理,这里简化只是来说明问题F2(list.GetRange(oneTimeNum * i, length))NextEnd SubPrivate Sub F2(ByVal al As ArrayList)'对ArrayList集合al进行处理End Sub


      2.普通除"/"和整数除"\"

      1)普通除:expression1 / expression2

      结果是 expression1 除以 expression2 的完整的商,包括任何余数。执行除法之前,任何整数数值表达式(除数和被除数)都会被扩展为 Double。如果将结果赋给整数数据类型,Visual Basic 会试图将结果从 Double 转换成这种类型。

      举例说明:30 / 18 = 1.6666666666666667,执行除法前被除数30和除数18都扩展为Double类型,结果也为Double类型。

      2)整数除:expression1 \ expression2

      结果是 expression1 除以 expression2 的整数商,它丢弃了所有余数,只保留整数部分(称为截断)。结果数据类型是数值类型,对应于 expression1 和 expression2 的数据类型。值得注意的一点,如果除数或被除数为浮点数,在执行除法前,编译器会采用“四舍六入五成双”的规则将其转换成Long类型,再执行除法。

      举例说明:30 / 18 = 1,只保留结果的整数部分。

      3.VB.NET中的类型转换(Double—>Integer)

      根据第二部分对普通除的解释,当CLR执行Dim oneTimeNum As Integer = 30 / 18时,首先将被除数30和除数18都扩展为Double类型,进行除运算得到Double类型的结果1.6666666666666667,因为要将Double类型数据赋值给Integer类型变量,此时要执行强制类型转换,得到最终结果oneTimeNum = 2(可能很多人和我一样会奇怪结果为什么不是1)。我们从IL代码中查看VB.NET中从Double—>Integer类型转换的实质。

.method public static void  F1(int32 times) cil managed
{// 代码大小       123 (0x7b).maxstack  3.locals init ([0] class [mscorlib]System.Collections.ArrayList list,[1] int32 oneTimeNum,[2] int32 i,[3] int32 V_3,[4] int32 length,[5] int32 VB$t_i4$L0,[6] int32 VB$CG$t_i4$S0,[7] bool VB$CG$t_bool$S0)IL_0000:  nopIL_0001:  newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()IL_0006:  stloc.0IL_0007:  ldc.i4.0IL_0008:  stloc.2IL_0009:  ldloc.0IL_000a:  ldloc.2IL_000b:  box        [mscorlib]System.Int32IL_0010:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::Add(object)IL_0015:  popIL_0016:  nopIL_0017:  ldloc.2IL_0018:  ldc.i4.1IL_0019:  add.ovfIL_001a:  stloc.2IL_001b:  ldloc.2IL_001c:  ldc.i4.s   29IL_001e:  stloc.s    VB$CG$t_i4$S0IL_0020:  ldloc.s    VB$CG$t_i4$S0IL_0022:  ble.s      IL_0009IL_0024:  ldloc.0IL_0025:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::get_Count()IL_002a:  conv.r8IL_002b:  ldarg.0IL_002c:  conv.r8IL_002d:  divIL_002e:  call       float64 [mscorlib]System.Math::Round(float64) //重点看这句IL_0033:  conv.ovf.i4IL_0034:  stloc.1IL_0035:  ldc.i4.0IL_0036:  ldarg.0IL_0037:  ldc.i4.1IL_0038:  sub.ovfIL_0039:  stloc.s    VB$t_i4$L0IL_003b:  stloc.3IL_003c:  br.s       IL_0070IL_003e:  ldloc.1IL_003f:  stloc.s    lengthIL_0041:  ldloc.3IL_0042:  ldarg.0IL_0043:  ldc.i4.1IL_0044:  sub.ovfIL_0045:  ceqIL_0047:  stloc.s    VB$CG$t_bool$S0IL_0049:  ldloc.s    VB$CG$t_bool$S0IL_004b:  brfalse.s  IL_0059IL_004d:  ldloc.0IL_004e:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::get_Count()IL_0053:  ldloc.1IL_0054:  ldloc.3IL_0055:  mul.ovfIL_0056:  sub.ovfIL_0057:  stloc.s    lengthIL_0059:  nopIL_005a:  ldloc.0IL_005b:  ldloc.1IL_005c:  ldloc.3IL_005d:  mul.ovfIL_005e:  ldloc.s    lengthIL_0060:  callvirt   instance class [mscorlib]System.Collections.ArrayList [mscorlib]System.Collections.ArrayList::GetRange(int32,int32)IL_0065:  call       void VBTest.Module1::F2(class [mscorlib]System.Collections.ArrayList)IL_006a:  nopIL_006b:  nopIL_006c:  ldloc.3IL_006d:  ldc.i4.1IL_006e:  add.ovfIL_006f:  stloc.3IL_0070:  ldloc.3IL_0071:  ldloc.s    VB$t_i4$L0IL_0073:  stloc.s    VB$CG$t_i4$S0IL_0075:  ldloc.s    VB$CG$t_i4$S0IL_0077:  ble.s      IL_003eIL_0079:  nopIL_007a:  ret
} // end of method Module1::F1


      从IL代码可以看出,VB.NET中执行类型转换实际上是调用的函数[mscorlib]System.Math::Round(float64),MSDN中对这个函数的解释:将双精度浮点值舍入为最接近的整数,如果参数为两个整数的中值,这两个整数一个为偶数,另一个为奇数,则返回偶数(也就是我们常说的“四舍六入五成双”)。
      现在,可以很好的解释文章开始提出的问题了:由于输入18时,oneTimeNum的值为2,当循环到第16次时i = 15,此时执行list.GetRange(oneTimeNum * i, length)list.GetRange(30,2),已经超出了list的长度范围,所以会抛出异常。

      4.C#和VB.NET的区别

      1)C#中的除运算"/"符相当于VB.NET的整数除"\"运算符;
      2)C#中从Double—>Integer类型转换必须要采用显示方式,且转换规则为直接舍弃小数位。

      总结这次出现问题的根源是用C#语法去推断VB.NET语法,因为接触C#较早,而C#和VB.NET语法又大同小异,忽略了对VB.NET基本语法的学习,以后应多注意两种语言的差别,尽量减少类似的错误。还有一点需要注意,遇到问题的时候多查MSDN,似乎现在都习惯从网上寻求答案,但网上关于VB.NET除运算符的内容并不多,找了半天,才发现MSDN上写的很详细,我想查找资料的顺序应该是:MSDN—>CNBlogs找找看—>Google/Baidu。


这篇关于小心VB.NET中的除运算符/和\的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/960008

相关文章

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

【重学 MySQL】十九、位运算符的使用

【重学 MySQL】十九、位运算符的使用 示例检查权限添加权限移除权限 在 MySQL 中,位运算符允许你直接在整数类型的列或表达式上进行位级操作。这些操作对于处理那些需要在二进制表示上进行直接修改或比较的场景特别有用,比如权限管理、状态标记等。 &(位与) 对两个数的二进制表示进行位与操作。只有两个相应的二进制位都为 1 时,结果的该位才为 1,否则为 0。 |(位

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变

第二十四章 rust中的运算符重载

注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust中的运算符重载 目录 注意一、前言二、基本使用三、常用运算符四、通用约束 一、前言 C/C++中有运算符重载这一概念,它的目的是让即使含不相干的内容也能通过我们自定义的方法进行运算符操作运算。 比如字符串本身是不能相加的,但由于C++中的String重载了运算符+,所以我们就可以将两个字符串进行相加、但实际

如何删除不小心上传到git远程仓库中的.idea .iml文件

如果在开始的时候不配置,gitignore文件或者文件配置不正确,初始化上传的时候就会有一些不必要的信息上传上去 如果已经存在了一些文件在git远程仓库中,如。idea,.iml文件等。 首先在项目中定义一个  .gitignore文件,简单的实例如下也可以用idea中的gitignore插件 .DS_Storeclasses/*.settings/target/.classpath

《C++中的移动构造函数与移动赋值运算符:解锁高效编程的最佳实践》

在 C++的编程世界中,移动构造函数和移动赋值运算符是提升程序性能和效率的重要工具。理解并正确运用它们,可以让我们的代码更加高效、简洁和优雅。 一、引言 随着现代软件系统的日益复杂和对性能要求的不断提高,C++程序员需要不断探索新的技术和方法来优化代码。移动构造函数和移动赋值运算符的出现,为解决资源管理和性能优化问题提供了有力的手段。它们允许我们在不进行不必要的复制操作的情况下,高效地转移资源

用VB创建开始菜单快捷方式(无需其他DLL)

Option Explicit   Private Sub Command1_Click()   CreateProgManGroup Me, "测试", "test.grp"   CreateProgManItem Me, "d:\ghost.exe", "Ghost"   CreateProgManItem Me, "d:\setupQQ.exe", "QQ"   End