如何防止PowerShell';是否阻止Measure Object cmdlet截断数据?

如何防止PowerShell';是否阻止Measure Object cmdlet截断数据?,powershell,measure-object,Powershell,Measure Object,我试图比较以下数据以获得最大的数字: $UserDeets name lastLogon ---- --------- Frank Ti 132273694413991065 Frank Ti 132279742884182029 Frank Ti 132282196073500496 Frank Ti 132272912975826719 Frank Ti 132282144707771693 Frank Ti 1322287

我试图比较以下数据以获得最大的数字:

$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
正如您所看到的,虽然它返回了正确的数据,但它截断了最后几个数字


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

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

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

$UserDeets = ($UserDeets | Sort-Object -Property LastLogon)
最高的对象将位于阵列的末端,可以如下方式获得:

$UserDeets[-1]

我想您可以通过检查多个DC来尝试获取用户的最新登录,我是通过以下代码来实现的(其中:
$samacc
-当前用户,
$controller
-所有DC主机名的列表):


这对我有用。将其从64位浮点转换回64位整数。但有些数字会稍微偏离(.00000000000000 5或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
在对该问题的评论中提供了关键的要点:

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

  • 曾报道过这种令人惊讶的行为
您输入的数字属于
[long]
类型,其值超过了
[double]
中可以精确表示的最高整数,即
9007199254740991
(您可以使用
[bigint]::pow(2,53)-1
进行计算)

一个有效的解决方法是使用LINQ():

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

另一种效率较低但更为PowerShell惯用的解决方法是使用排序,类似于:

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



[1] 请注意,对于
-Min
-Max
也可以接受非数字输入,只要它们实现了接口,在这种情况下,输入保持原样,不会发生精度损失;e、 例如,
'c','b','a'|度量对象-最小值
[datetime]::现在,[datetime]::现在。AddDays(1)|度量对象-最大值
工作正常,因为类型
[string]
[datetime]
两者都实现了
i可比较

有趣的-看起来
度量对象
将产生一个
双精度
,即使其输入是
Int64
。这不仅仅是一个格式问题,因为
Double
不能精确地保存
Int64
的每个值。请尝试
[System.Linq.Enumerable]::Max([long[]($userDeets.lastLogon))
(依赖Linq而不是M-O)。感谢您的回复。很高兴知道这不起作用的实际原因。我确实找到了一个解决办法。你可以转换日期时间,然后通过排序来获取最新的日期。它对这个特定的值有效,但很幸运。如果最大值为
13228219607750497
测量对象
将无法生成它,因为该值无法在
double
中以足够的精度表示@Jeroenmoster您是对的。我想如果在转换powershell之前很久,它可能会保持精度。它保持在1322821960750496。@Jeroemostert你是怎么得到这个数字的?我从问题中取出1322821960750496并加上1.:-)没有魔法;无法正确表示微小差异的事实是浮点运算方式的一个简单结果。我不知道13228219607350496是完全可以代表的,但这是一个令人高兴的巧合(例如,132272912975826719不是)。下一个可以精确表示的数字是1322821960750512。它们之间的差值是16,这当然不是巧合的2的幂。@Jeroemostert哦,我明白了,我认为这是一个最大值。
$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
[Linq.Enumerable]::Max(
  [long[]] $UserDeets.lastLogon
)
# Sort the LastLogon property values, then grab the *last* one,
# which is the largest value.
($UserDeets.LastLogon | Sort-Object)[-1]