VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 936|回复: 8

求教:Vb.net下的一个数值问题

[复制链接]

1

主题

4

帖子

5.00

积分

新手上路

Rank: 1

积分
5.00
发表于 2020-1-30 00:00:02 | 显示全部楼层 |阅读模式
我有一个程序段:For循环
dim y1BeginData as single=-4.0f
dim y1KdValue as singel=0.8f
......
for ykdIdx as integer=0 to 10
  dim ykdV as single=y1BeginData+ykdIdx*y1KdValue
  ......
next

在这个程序段运行时,竟然出现当ykdIdx=3时,ykdV=-1.5999999
当ykdIdx=4时,ykdV=-0.799999952;当ykdIdx=5时,ykdV=0.0000000596046448;当ykdIdx=6时,ykdV=0.8000001;当ykdIdx=7时,ykdV=1.60000014;其他值正常,而实际上这几个值分别应为:-1.6,-0.8,0,0.8,1.6;请教一下,出现这个情况到底是怎么回事,如何解决?谢谢
回复

使用道具 举报

1

主题

4

帖子

5.00

积分

新手上路

Rank: 1

积分
5.00
 楼主| 发表于 2020-3-6 21:15:01 | 显示全部楼层
等了半天,最后还是自己解决,我把single换成double就解决了,估计是数值转换时出的问题.
回复

使用道具 举报

1

主题

4

帖子

5.00

积分

新手上路

Rank: 1

积分
5.00
 楼主| 发表于 2020-3-7 06:30:01 | 显示全部楼层
但是,具体为什么,我还没弄明白,希望诸位帮个忙,弄个明白是为什么会这样
回复

使用道具 举报

0

主题

1

帖子

2.00

积分

新手上路

Rank: 1

积分
2.00
发表于 2020-4-23 10:45:01 | 显示全部楼层
这正是计算机常见的问题:要知道计算机是以二进制数来表示任何数值的,自然,文体究出来了:并不是所有的小数都可以用二进制浮点数精确表示,而是表示为最靠近它的临近区分出来的小数!
回复

使用道具 举报

1

主题

9

帖子

8.00

积分

新手上路

Rank: 1

积分
8.00
发表于 2020-4-28 17:15:01 | 显示全部楼层
浮点数有个精度的问题,当你没有指定精度时(小数位数)时结果可能不准,如果你想小数点后留一位你可以这样做:把你的数乘10,再取整,最后再除以10,这样就结果正确了.

CInt(yournumber*10)/10

结帐吧,你按照我的做一定会解决问题!
回复

使用道具 举报

1

主题

4

帖子

5.00

积分

新手上路

Rank: 1

积分
5.00
 楼主| 发表于 2020-7-22 01:00:01 | 显示全部楼层
感谢nijiaoshaa很上面这位朋友,不过问题还是没解决,Single和Double,Double计算正确而Single计算就出这个问题.
回复

使用道具 举报

0

主题

11

帖子

7.00

积分

新手上路

Rank: 1

积分
7.00
发表于 2020-7-23 00:30:01 | 显示全部楼层
wangfan45正解
回复

使用道具 举报

0

主题

3

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
发表于 2020-8-3 10:15:01 | 显示全部楼层
在使用浮点数(Single 数据类型 (Visual Basic) 和 Double 数据类型 (Visual Basic))时,请记住,它们作为二进位分式存储。这就意味着,对于任何非二进位分式(形式为 k / (2 ^ n,其中 k 和 n 均为整数)的数量,浮点数无法保存它们的精确表示形式。例如,0.5 (= 1/2) 和 0.3125 (= 5/16) 可保存为精确的值,而 0.2 (= 1/5) 和 0.3 (= 3/10) 只能是近似值。

由于这一不精确性,因此,在处理浮点值时,不能指望会获得精确的结果。具体而言,理论上相等的两个值可能会具有略微不同的表示形式。

比较浮点数量
使用 System 命名空间中的 Math 类的 Abs 方法,计算各数量之间的差值的绝对值。

确定可接受的最大差值,这样一来,如果两个数量之间的差值不超过此值,则可以认为这两个数量实际上是相等的。

将差值的绝对值与可接受的差值进行比较。

下面的示例演示有关两个 Double 值的正确和错误的比较。

Visual Basic  复制代码
Dim oneThird As Double = 1.0 / 3.0
Dim pointThrees As Double = 0.333333333333333

' The following comparison does not indicate equality.
Dim exactlyEqual As Boolean = (oneThird = pointThrees)

' The following comparison indicates equality.
Dim closeEnough As Double = 0.000000000000001
Dim absoluteDifference As Double = Math.Abs(oneThird - pointThrees)
Dim practicallyEqual As Boolean = (absoluteDifference < closeEnough)

MsgBox("1.0 / 3.0 is represented as " & oneThird.ToString("G17") _
  & vbCrLf & "0.333333333333333 is represented as " _
  & pointThrees.ToString("G17") _
  & vbCrLf & "Exact comparison generates " & CStr(exactlyEqual) _
  & vbCrLf & "Acceptable difference comparison generates " _
  & CStr(practicallyEqual))



上面的示例使用了 Double 结构的 ToString 方法,因此,它可以指定比在使用 CStr 关键字时更高的精度。默认精度是 15 位数字,但“G17”格式将其扩展到 17 位数字。

Mod 运算符未返回准确的结果
由于浮点存储的不精确性,如果至少一个操作数为浮点数,Mod 运算符 (Visual Basic) 可能会返回意外的结果。

Decimal 数据类型 (Visual Basic) 不使用浮点表示形式。在 Single 和 Double 中不精确的许多数字在 Decimal 中是精确的数字(例如 0.2 和 0.3)。虽然浮点表示形式在算术运算速度上比 Decimal 表示形式快,但可能值得用性能的下降换回精度的提高。

找出浮点数量的整数余数
将变量声明为 Decimal。

使用文本类型字符 D 将文本强制转换为 Decimal,以防文本的值相对于 Long 数据类型太大。

下面的示例演示了浮点操作数潜在的不精确性。

Visual Basic  复制代码
Dim two As Double = 2.0
Dim zeroPointTwo As Double = 0.2
Dim quotient As Double = two / zeroPointTwo
Dim doubleRemainder As Double = two Mod zeroPointTwo

MsgBox("2.0 is represented as " & two.ToString("G17") _
  & vbCrLf & "0.2 is represented as " & zeroPointTwo.ToString("G17") _
  & vbCrLf & "2.0 / 0.2 generates " & quotient.ToString("G17") _
  & vbCrLf & "2.0 Mod 0.2 generates " _
  & doubleRemainder.ToString("G17"))

Dim decimalRemainder As Decimal = 2D Mod 0.2D
MsgBox("2.0D Mod 0.2D generates " & CStr(decimalRemainder))



上面的示例使用了 Double 结构的 ToString 方法,因此,它可以指定比在使用 CStr 关键字时更高的精度。默认精度是 15 位数字,但“G17”格式将其扩展到 17 位数字。

由于 zeroPointTwo 是 Double,因此,它表示的 0.2 这个值是一个无限重复的二进位分式(存储的值是 0.20000000000000001)。将 2.0 除以此数量将得到 9.9999999999999995,余数为 0.19999999999999991。

在 decimalRemainder 的表达式中,文本类型字符 D 将两个操作数均强制转换为 Decimal,这样 0.2 将具有精确的表示形式。因此,Mod 运算符将得到预期的余数 0.0。

请注意,将 decimalRemainder 声明为 Decimal 还不够。您还必须将文本强制转换为 Decimal,否则它们将默认为 Double,而且 decimalRemainder 将与 doubleRemainder 一样均收到不准确的值。


MSDN 2005
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vbalr/html/90040d67-b630-4125-a6ae-37195b079042.htm
回复

使用道具 举报

0

主题

4

帖子

5.00

积分

新手上路

Rank: 1

积分
5.00
发表于 2020-8-4 18:30:01 | 显示全部楼层
楼上回答到位了,应该是二进制分式存储的问题
学习了
hoho,收藏
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

快速回复 返回顶部 返回列表