4

我正在尝试比较以下数据以获得最大的数字:

$UserDeets 

name                 lastLogon
----                 ---------
Frank Ti 132273694413991065
Frank Ti 132279742884182029
Frank Ti 132282196073500496
Frank Ti 132272912975826719
Frank Ti 132282144707771693
Frank Ti 132228790551703041

为此,我尝试使用内置的“测量”功能。这是我正在执行的代码

($UserDeets| measure -Property lastLogon -Maximum ).Maximum

结果如下

1.322821960735E+17

正如您所看到的,它正在返回正确的数据,它正在截断最后几位数字。

有没有办法防止这种截断?

4

4 回答 4

1

Jeroen Mostert在对该问题的评论中提供了关键的指示:

不幸的是,从 PowerShell 7.0 开始,Measure-Object总是将其、、和操作的输入数字[1]转换为( )并将结果报告为该类型,这可能会导致精度损失。-Sum-Maximum-Minimum-Average-StandardDeviation[double]System.Double

您的输入数字是 type [long],并且它们的值超过了可以在 a 中精确表示的最大整数,[double]9007199254740991(您可以使用 计算它[bigint]::pow(2, 53) - 1

一种有效的解决方法是使用 LINQ ( System.Linq.Enumerable.Max):

[Linq.Enumerable]::Max(
  [long[]] $UserDeets.lastLogon
)

请注意,[long[]]为了使 PowerShell 能够.Max()使用具体类型调用泛型方法,需要显式转换。

另一种效率较低但更符合 PowerShell 习惯的解决方法是使用排序,类似于OP 自己的答案

# Sort the LastLogon property values, then grab the *last* one,
# which is the largest value.
($UserDeets.LastLogon | Sort-Object)[-1]

仅对值数组.lastLogon而不是完整的输入对象进行排序,可以最大限度地减少创建重复的排序数组的概念上不必要的开销,从而达到最大值。值可以确定。


[1] 请注意,for-Min-Max 非数字输入也被接受,只要它们实现System.IComparable接口,在这种情况下,输入保持原样并且不会发生精度损失;例如,'c', 'b', 'a' | Measure-Object -Minimum并且[datetime]::now, [datetime]::now.AddDays(1) | Measure-Object -Maximum工作正常,因为类型[string][datetime]两者都实现IComparable.

于 2020-03-09T22:10:32.330 回答
0

好的,我有一个解决方案。答案是不要使用“度量”。这是一种解决方法,但它得到了想要的答案。

首先我对数组进行了排序:

$UserDeets = ($UserDeets | Sort-Object -Property LastLogon)

最高的对象将位于数组的末尾,可以像这样获得:

$UserDeets[-1]
于 2020-03-09T10:45:36.240 回答
0

我认为您尝试通过检查多个 DC 来获取用户的最新登录信息,我通过以下代码执行此操作(其中:$samacc-当前用户,$controller-所有 DC 主机名的列表。):

$scriptblock={
    param($samacc,$controller)
    $result=@()
    foreach($cont in $controller){
    $RESULT=$result + (Get-ADUser -Server $cont -Identity $samacc -Properties lastlogon,whenchanged,displayname,title,company  | sort-object lastLogon -descending | select-object enabled,displayname,samaccountname,title,company, @{Name="lastLogon";Expression={[datetime]::FromFileTime($_.'lastLogon')}},whenchanged)
    }
    $result|Sort-Object -Descending -Property LastLogon|select -First 1
    }
于 2020-03-09T11:01:36.907 回答
-1

这对我有用。将其从 64 位浮点数转回 64 位整数。但是如果是日期时间,有些数字会稍微偏离(0.000000000000005 或 5/1 万亿 % 错误),或者 6 百万分之一秒(滴答声)。

$jsontext = @'
[ { name: 'Frank Ti', lastLogon: 132273694413991065 },
  { name: 'Frank Ti', lastLogon: 132279742884182029 },
  { name: 'Frank Ti', lastLogon: 132282196073500496 },
  { name: 'Frank Ti', lastLogon: 132272912975826719 },
  { name: 'Frank Ti', lastLogon: 132282144707771693 },
  { name: 'Frank Ti', lastLogon: 132228790551703041 },
  { name: 'Frank Ti', lastLogon: 132282196073500499 },
  { name: 'Frank Ti', lastLogon:   9007199254740991 } ]
'@

$userdeets = $jsontext | convertfrom-json
[long]($userdeets | measure lastlogon -Maximum).maximum

132282196073500496
于 2020-03-09T13:06:14.817 回答