【问题标题】:VBS script return expected result, how to compare float value?VBS 脚本返回预期结果,如何比较浮点值?
【发布时间】:2014-06-30 19:46:53
【问题描述】:

执行以下 VB 脚本时,我得到了一个有趣的结果。

Set StdOut = WScript.StdOut
Set wbemSvc = GetObject("winmgmts://" & "." & "/root/cimv2")
Set biosSet = wbemSvc.ExecQuery("Select * from Win32_BIOS")

For Each biosObj In biosSet
  StdOut.WriteLine "SMBIOSMajorVersion=" & biosObj.SMBIOSMajorVersion
  StdOut.WriteLine "SMBIOSMinorVersion=" & biosObj.SMBIOSMinorVersion
Next

  StdOut.WriteLine "Return value is: " & IsNewBiosVersion

Function IsNewBiosVersion()

  On Error Resume Next
  Set biosSet = wbemSvc.ExecQuery("Select * from Win32_BIOS")

  newBios = 0
  For Each bios In biosSet
    minorFloat = "." & bios.SMBIOSMinorVersion
    If bios.SMBIOSMajorVersion > 2 OR (bios.SMBIOSMajorVersion = 2 AND minorFloat >= .6) Then
      newBios = 1
    End If
  Next
  IsNewBiosVersion = newBios

End Function

结果如下。这看起来很矛盾,因为SMBIOSMinorVersion=4,根据脚本中的代码逻辑,返回值应该是0!!!

SMBIOSMajorVersion=2
SMBIOSMinorVersion=4
Return value is: 1

我在另一个系统上运行了相同的脚本并得到了预期的正确结果。

SMBIOSMajorVersion=2
SMBIOSMinorVersion=4
Return value is: 0

那么这里的问题是什么?

新更新:

我们在系统上再次执行以下脚本,发现CDbl()函数没有正确地将字符串“2.4”转换为double值,而是将其转换为24!看起来像点“。”转换时丢失了,这是怎么回事? CDbl有BUG还是使用时违规?

这是脚本

Set StdOut = WScript.StdOut
StdOut.WriteLine ""
StdOut.WriteLine "Simple Function to Test BIOS Version"
StdOut.WriteLine ""
Set wbemSvc = GetObject("winmgmts://" & "." & "/root/cimv2")
Set biosSet = wbemSvc.ExecQuery("Select * from Win32_BIOS")

For Each bios In biosSet
  newBios = 0
  StdOut.WriteLine "SMBIOSMajorVersion=" & bios.SMBIOSMajorVersion
  StdOut.WriteLine "SMBIOSMinorVersion=" & bios.SMBIOSMinorVersion
  temp = bios.SMBIOSMajorVersion & "." & bios.SMBIOSMinorVersion
  StdOut.WriteLine "major dot minor=" & temp

  currentBios = CDbl(bios.SMBIOSMajorVersion & "." & bios.SMBIOSMinorVersion)
  StdOut.WriteLine ""
  StdOut.WriteLine "currentBios=" & currentBios
  If currentBios >= 2.6 Then newBios = 1
  StdOut.WriteLine "return value is: " & newBios
Next

这是输出

Simple Function to Test BIOS Version

SMBIOSMajorVersion=2
SMBIOSMinorVersion=4
major dot minor=2.4

currentBios=24
return value is: 1

【问题讨论】:

  • 您是否检查过有多少 Win32_BIOS 对象被返回到biosSet
  • 哎呀,我应该放这个 --> StdOut.WriteLine "Return value is: " & IsNewBiosVersion, 在循环中,但是没有坏处,因为在两个系统中,只有一个 Win32_BIOS 对象是返回biosSet

标签: vb.net windows vbscript


【解决方案1】:

删除您的错误处理 - 它可能会抑制问题。

On Error Resume Next ' Not a good idea

一方面,您在这些行中将字符串与双精度进行比较:

minorFloat = "." & bios.SMBIOSMinorVersion
If bios.SMBIOSMajorVersion > 2 OR (bios.SMBIOSMajorVersion = 2 AND minorFloat >= .6) Then

【讨论】:

  • 但是如何解释在另一个系统上返回值为0呢?
  • 在您正确比较从系统中提取的数据之前,您无法解释系统之间的差异。例如,根据我的另一条评论,另一台机器可能会随机返回真正的 BIOS 对象和另一个空/假/错误的对象,这会覆盖循环中的“真实”结果。
  • Sam,看起来原因是 CDbl 没有将“2.4”转换为正确的值。请参阅上面的我的新更新。有什么想法吗?
【解决方案2】:

为什么不将major.minor 值转换为浮点数进行测试?您目前正在做两个单独的测试,其中一个是字符串与浮点数的比较,这是不寻常的。

也许试试这个?

currentBios = CDbl(bios.SMBIOSMajorVersion & "." & bios.SMBIOSMinorVersion)

If currentBios >= 2.6 Then newBios = 1

当涉及数学运算时,您必须小心比较浮点值,但对于文字值,您会没事的。

并且,如前所述,删除 On Error Resume Next 否则您可能永远不知道为什么它可以在一台 PC 上运行,而不能在另一台 PC 上运行。

【讨论】:

  • 在VB中以这种方式“currentBios >= 2.6”比较双值是否是个好主意?让我检查一下...
  • 而且据我所知,字符串和double比较时,字符串会先转换成double,不是吗?
  • VBS 可能会将字符串转换为双精度,是的。但为了安全起见,我会明确地将它们转换为相同的类型。在我的示例中,currentBios 被强制转换为 double,以便可以将其与文字 double (2.6) 进行比较。因此,我们将苹果与苹果进行比较(或双打与双打,如果您愿意的话)。
  • 我保留这行“On Error Resume Next”,但用上面建议的代码替换比较代码,但仍然得到不正确的返回值 1。我又想不通了,知道吗?
  • 邦德,我们发现了一些有趣的东西,请参阅上面“新更新:”字段下的描述。如您所见,CDbl 将“2.4”转换为 24!你知道这里发生了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多