Skip to content

Commit

Permalink
Add examples of differing accuracy.
Browse files Browse the repository at this point in the history
  • Loading branch information
atmoos committed Nov 26, 2023
1 parent b95d012 commit a9fae0c
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using UnitsNet;
using Quantities.Units.Si.Metric;
using Quantities.Units.Si.Metric.UnitsOfInformation;
using Quantities.Units.Si.Derived;
using Quantities.Units.Imperial.Temperature;
using Quantities.Units.NonStandard.Temperature;

using nLength = UnitsNet.Length;
using nTemperature = UnitsNet.Temperature;
using Bytes = Quantities.Units.Si.Metric.UnitsOfInformation.Byte;

namespace Quantities.Test.Compare;

public class QuantitiesAndUnitsNetAreEquallyAccurate
{
[Fact]
public void ÅngströmToNanoMetre()
{
const Double expectedNanoMetre = 1d;

// Quantities
Length ångström = Length.Of(10, Metric<Ångström>());
Length nanoMetres = ångström.To(Si<Nano, Metre>());

// UnitsNet
nLength nÅngström = nLength.FromAngstroms(10);
nLength nNanoMetre = nÅngström.ToUnit(UnitsNet.Units.LengthUnit.Nanometer);

// Equally precise
Assert.Equal(expectedNanoMetre, nanoMetres);
Assert.Equal(expectedNanoMetre, nNanoMetre.Value);
}

[Fact]
public void GibiBitPerHourToKiloBytePerMinute()
{
const Double expectedRate = 1024d * 1024d * 1024d / 1000d;

// Quantities
DataRate speed = DataRate.Of(8, Binary<Gibi, Bit>().Per(Si<Second>()));
DataRate actual = speed.To(Metric<Kilo, Bytes>().Per(Si<Second>()));

// UnitsNet
BitRate nSpeed = BitRate.FromGibibitsPerSecond(8);
BitRate nActual = nSpeed.ToUnit(UnitsNet.Units.BitRateUnit.KilobytePerSecond);

// Equally precise
Assert.Equal(expectedRate, actual);
Assert.Equal(expectedRate, (Double)nActual.Value); // but Value is a Decimal here :-/
}

[Fact]
public void CelsiusToFahrenheit()
{
const Double expectedFahrenheit = 98.6;

// Quantities
Temperature temperature = Temperature.Of(37.0, Metric<Celsius>());
Temperature actual = temperature.To(Imperial<Fahrenheit>());

// UnitsNet
nTemperature nTemperature = nTemperature.FromDegreesCelsius(37.0);
nTemperature nActual = nTemperature.ToUnit(UnitsNet.Units.TemperatureUnit.DegreeFahrenheit);

// Equally precise :-)
Assert.Equal(expectedFahrenheit, actual);
Assert.Equal(expectedFahrenheit, nActual.Value);
}

[Fact]
public void KelvinToRømer()
{
const Double expectedRømer = -1.8345; // calculated using full precision math.

// Quantities
Temperature temperature = Temperature.Of(255.37, Si<Kelvin>());
Temperature actual = temperature.To(NonStandard<Rømer>());

// UnitsNet
nTemperature nTemperature = nTemperature.FromKelvins(255.37);
nTemperature nActual = nTemperature.ToUnit(UnitsNet.Units.TemperatureUnit.DegreeRoemer);

// Quantities and UnitsNet are equally bad (measured by precision parameter only)
Assert.Equal(expectedRømer, actual, 13); // -1.8344999999999885
Assert.Equal(expectedRømer, nActual.Value, 13); // -1.83449999999999
}
}
116 changes: 116 additions & 0 deletions source/Quantities.Test/Compare/QuantitiesIsMoreAccurateThanUnitsNet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using Quantities.Units.Si.Metric;
using Quantities.Units.Imperial.Area;
using Quantities.Units.Imperial.Mass;

using nArea = UnitsNet.Area;
using nLength = UnitsNet.Length;
using nMass = UnitsNet.Mass;
using nVolume = UnitsNet.Volume;

namespace Quantities.Test.Compare;

public class QuantitiesIsMoreAccurateThanUnitsNet
{
[Fact]
public void SquareMilesToSquareKilometres()
{
Double expectedSqKiloMetre = 5.179976220672; // 2×1.609344×1.609344 using full precision math.

// Quantities
Area squareMiles = Area.Of(2, Square(Imperial<Mile>()));
Area actual = squareMiles.To(Square(Si<Kilo, Metre>()));

// UnitsNet
nArea nSquareMiles = nArea.FromSquareMiles(2);
nArea nActual = nSquareMiles.ToUnit(UnitsNet.Units.AreaUnit.SquareKilometer);

// Quantities is marginally more accurate that UnitsNet
Assert.Equal(expectedSqKiloMetre, actual);
Assert.Equal(expectedSqKiloMetre, nActual.Value, 14); // two digits less accurate.

// Sanity check
Double roundRobinSqMiles = actual.To(Square(Imperial<Mile>()));
Double nRoundRobinSqMiles = nActual.ToUnit(UnitsNet.Units.AreaUnit.SquareMile).Value;
Assert.Equal(2d, roundRobinSqMiles);
Assert.Equal(2d, nRoundRobinSqMiles);
}

[Fact]
public void SquareFeetTimesYards()
{
const Double expectedCubicFeet = 162;

// Quantities
Area area = Area.Of(27, Square(Imperial<Foot>()));
Length length = Length.Of(2, Imperial<Yard>());

Volume actual = area * length;

// UnitsNet
nArea nA = nArea.FromSquareFeet(27);
nLength nL = nLength.FromYards(2);

nVolume nActualInCubicMetres = nA * nL; // results in m³
// need to convert to cubic feet first...
nVolume nActual = nActualInCubicMetres.ToUnit(UnitsNet.Units.VolumeUnit.CubicFoot);

// Quantities is marginally more accurate that UnitsNet
Assert.Equal(expectedCubicFeet, actual);
Assert.Equal(expectedCubicFeet, nActual.Value, 13);

// Benefit of the doubt, let's check UnitsNet default answer: m³
const Double expectedCubicMetre = 4.587329147904; // 162×(0.3048×0.3048×0.3048) using full precision math
Volume cubicMetre = actual.To(Cubic(Si<Metre>()));
Assert.Equal(expectedCubicMetre, cubicMetre); // is accurate
Assert.Equal(expectedCubicMetre, nActualInCubicMetres.Value); // is also accurate
}

[Fact]
public void PureArealDimensionDividedByLength()
{
const Double expectedYards = 16;

// Quantities
Area area = Area.Of(2, Imperial<Acre>());
Length length = Length.Of(1815, Imperial<Foot>());

Length actual = area / length;

// UnitsNet
nArea nA = nArea.FromAcres(2);
nLength nL = nLength.FromFeet(1815);

nLength nActualInMeters = nA / nL; // is in m
// need to convert to yards first
nLength nActual = nActualInMeters.ToUnit(UnitsNet.Units.LengthUnit.Yard);

// Quantities is marginally more accurate that UnitsNet
Assert.Equal(expectedYards, actual);
Assert.Equal(expectedYards, nActual.Value, 14);

// Benefit of the doubt, let's check UnitsNet default answer: m
const Double expectedMetre = 14.6304; // 16×0.9144 using full precision math
Length metres = actual.To(Si<Metre>());
Assert.Equal(expectedMetre, metres); // is accurate
Assert.Equal(expectedMetre, nActualInMeters.Value, 14); // is less accurate
}

[Fact]
public void GramToPound()
{
const Double expectedPounds = 3d;
const Double gramsInPound = 453.59237; // this is the definition of the pound in grams...

// Quantities
Mass mass = Mass.Of(expectedPounds * gramsInPound, Metric<Gram>());
Mass actual = mass.To(Imperial<Pound>());

// UnitsNet
nMass nMass = nMass.FromGrams(expectedPounds * gramsInPound);
nMass nActual = nMass.ToUnit(UnitsNet.Units.MassUnit.Pound);

// Quantities is marginally more accurate that UnitsNet
Assert.Equal(expectedPounds, actual);
Assert.Equal(expectedPounds, nActual.Value, 15);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Quantities.Test.Compare;

public class UnitsNetIsMoreAccurateThanQuantities
{
[Fact(Skip = "No known examples so far")]
public void NoKnownExamplesSoFar() { }
}
4 changes: 4 additions & 0 deletions source/Quantities.Test/Quantities.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@
<ProjectReference Include="..\Quantities.Units\Quantities.Units.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="UnitsNet" Version="5.36.0" />
</ItemGroup>

</Project>

0 comments on commit a9fae0c

Please sign in to comment.