Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public sealed class GenericMeasureInfo : MeasureInfo
/// </summary>
public GenericMeasureInfo()
{
Average = Sum = Maximum = Minimum = null;
Average = Sum = Maximum = Minimum = StandardDeviation = null;
}

/// <summary>
Expand Down Expand Up @@ -71,6 +71,11 @@ public GenericMeasureInfo()
///
/// </summary>
public double? Minimum { get; set; }

/// <summary>
/// The Standard Deviation of property values.
/// </summary>
public double? StandardDeviation { get; set; }
}

/// <summary>
Expand All @@ -90,7 +95,7 @@ public sealed class GenericObjectMeasureInfo : MeasureInfo
/// </summary>
public GenericObjectMeasureInfo()
{
Average = Sum = null;
Average = Sum = StandardDeviation = null;
Maximum = Minimum = null;
}

Expand Down Expand Up @@ -128,6 +133,11 @@ public GenericObjectMeasureInfo()
///
/// </summary>
public object Minimum { get; set; }

/// <summary>
/// The Standard Deviation of property values.
/// </summary>
public double? StandardDeviation { get; set; }
}

/// <summary>
Expand Down Expand Up @@ -225,6 +235,8 @@ private class Statistics

// Generic/Numeric statistics
internal double sum = 0.0;
internal double sumPrevious = 0.0;
internal double variance = 0.0;
internal object max = null;
internal object min = null;

Expand Down Expand Up @@ -263,6 +275,24 @@ public MeasureObjectCommand()

#endregion Common parameters in both sets

/// <summary>
/// Set to true if Standard Deviation is to be returned.
/// </summary>
[Parameter(ParameterSetName = GenericParameterSet)]
public SwitchParameter StandardDeviation
{
get
{
return _measureStandardDeviation;
}
set
{
_measureStandardDeviation = value;
}
}

private bool _measureStandardDeviation;

/// <summary>
/// Set to true is Sum is to be returned
/// </summary>
Expand Down Expand Up @@ -525,7 +555,7 @@ private void AnalyzeValue(string propertyName, object objValue)
AnalyzeString(strValue, stat);
}

if (_measureAverage || _measureSum)
if (_measureAverage || _measureSum || _measureStandardDeviation)
{
double numValue = 0.0;
if (!LanguagePrimitives.TryConvertTo(objValue, out numValue))
Expand Down Expand Up @@ -708,8 +738,19 @@ private void AnalyzeString(string strValue, Statistics stat)
/// </summary>
private void AnalyzeNumber(double numValue, Statistics stat)
{
if (_measureSum || _measureAverage)
if (_measureSum || _measureAverage || _measureStandardDeviation)
{
stat.sumPrevious = stat.sum;
stat.sum += numValue;
}
if (_measureStandardDeviation && stat.count > 1)
{
// Based off of iterative method of calculating variance on
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
double avgPrevious = stat.sumPrevious / (stat.count - 1);
stat.variance *= (stat.count - 2.0) / (stat.count - 1);
stat.variance += (numValue - avgPrevious) * (numValue - avgPrevious) / stat.count;
}
}

/// <summary>
Expand Down Expand Up @@ -790,15 +831,22 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene
{
double? sum = null;
double? average = null;
double? StandardDeviation = null;
object max = null;
object min = null;

if (!_nonNumericError)
{
if (_measureSum)
sum = stat.sum;

if (_measureAverage && stat.count > 0)
average = stat.sum / stat.count;

if (_measureStandardDeviation)
{
StandardDeviation = Math.Sqrt(stat.variance);
}
}

if (_measureMax)
Expand Down Expand Up @@ -835,6 +883,7 @@ private MeasureInfo CreateGenericMeasureInfo(Statistics stat, bool shouldUseGene
gmi.Count = stat.count;
gmi.Sum = sum;
gmi.Average = average;
gmi.StandardDeviation = StandardDeviation;
if (null != max)
{
gmi.Maximum = (double)max;
Expand Down Expand Up @@ -887,7 +936,7 @@ private TextMeasureInfo CreateTextMeasureInfo(Statistics stat)

/// <summary>
/// Whether or not a numeric conversion error occurred.
/// If true, then average/sum will not be output.
/// If true, then average/sum/standard deviation will not be output.
/// </summary>
private bool _nonNumericError = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Describe "Measure-Object" -Tags "CI" {
BeforeAll {
$testObject = 1,3,4
$testObject2 = 1..100
}

It "Should be able to be called without error" {
Expand All @@ -17,6 +18,51 @@ Describe "Measure-Object" -Tags "CI" {
$($testObject | Measure-Object).Count | Should Be $testObject.Length
}

It "Should calculate Standard Deviation" {
$actual = ($testObject | Measure-Object -StandardDeviation)
# We check this way since .StandardDeviation returns a double value
# 1.52752523165195 was calculated outside powershell using formula from
# http://mathworld.wolfram.com/StandardDeviation.html
[Math]::abs($actual.StandardDeviation - 1.52752523165195) | Should -BeLessThan .00000000000001
}


It "Should calculate Standard Deviation" {
$actual = ($testObject2 | Measure-Object -StandardDeviation)
# We check this way since .StandardDeviation returns a double value
# 29.011491975882 was calculated outside powershell using formula from
# http://mathworld.wolfram.com/StandardDeviation.html
[Math]::abs($actual.StandardDeviation - 29.011491975882) | Should -BeLessThan .0000000000001
}

It "Should calculate Standard Deviation with -Sum" {
$actual = ($testObject | Measure-Object -Sum -StandardDeviation)
# We check this way since .StandardDeviation returns a double value
$actual.Sum | Should Be 8
# 1.52752523165195 was calculated outside powershell using formula from
# http://mathworld.wolfram.com/StandardDeviation.html
[Math]::abs($actual.StandardDeviation - 1.52752523165195) | Should -BeLessThan .00000000000001
}

It "Should calculate Standard Deviation with -Average" {
$actual = ($testObject | Measure-Object -Average -StandardDeviation)
# We check this way since .StandardDeviation returns a double value
[Math]::abs($actual.Average - 2.66666666666667) | Should -BeLessThan .00000000000001
# 1.52752523165195 was calculated outside powershell using formula from
# http://mathworld.wolfram.com/StandardDeviation.html
[Math]::abs($actual.StandardDeviation - 1.52752523165195) | Should -BeLessThan .00000000000001
}

It "Should calculate Standard Deviation with -Sum -Average" {
$actual = ($testObject2 | Measure-Object -Sum -Average -StandardDeviation)
# We check this way since .StandardDeviation returns a double value
$actual.Sum | Should Be 5050
$actual.Average | Should Be 50.5
# 29.011491975882 was calculated outside powershell using formula from
# http://mathworld.wolfram.com/StandardDeviation.html
[Math]::abs($actual.StandardDeviation - 29.011491975882) | Should -BeLessThan .0000000000001
}

It "Should be able to count using the Property switch" {
$expected = $(Get-ChildItem $TestDrive).Length
$actual = $(Get-ChildItem $TestDrive | Measure-Object -Property Length).Count
Expand Down