When does a double become NaN? - c#

I am trying to understand which circumstances can cause a double to become NaN.
For instance, 0/0 is nan. This is also stated in the official Documentation.
https://learn.microsoft.com/en-us/dotnet/api/system.double.nan?view=net-6.0
However, my debug code indicates that the division is not by 0:
public class StandardDeviation
{
public StandardDeviation()
{
Clear();
}
private double M { get; set; }
private double S { get; set; }
private uint Iteration { get; set; }
public double Value
{
get
{
return Math.Sqrt(S / (Iteration - 2));
}
}
public void AddValue(double value)
{
if (double.IsNaN(value))
{
throw new ArgumentException("value IS nan!");
}
double tmpM = M;
M += (value - tmpM) / Iteration;
S += (value - tmpM) * (value - M);
Iteration++;
if (double.IsNaN(M))
{
Console.WriteLine($"\nNAN EXCEPTION!!! divide by: {Iteration}");
Console.WriteLine($"\nNAN EXCEPTION!!! tmpM: {tmpM}");
throw new ArgumentException("m IS nan!");
}
}
public void Clear()
{
M = 0.0;
S = 0.0;
Iteration = 1;
}
}
console message:
NAN EXCEPTION!!! divide by: 3
NAN EXCEPTION!!! tmpM: ∞
The issue primairly seems to be prevalent in release configuration, which makes it hard to debug.
Whenever the exception is thrown, Iteration = 3.

Related

Why does JsonConvert deserialize object fail with int but not long

When testing av web API created in .Net 6.0, we found that when a user of the API sent decimal number on a int you got a 400 error stating that it fail to parse the json because of the decimal on the int value. But doing the same on a long value worked fine it just removed the decimal numbers.
So to test if this (guessing that MS uses Newonsoft.Json), I made a little cmd test app to test the scenario. And the same thing happens there long pareses loosing it decimals, and int fails.
So is this a bug in the parser or by design?
[Edit] Should it not also fail on long?
using Newtonsoft.Json;
var data = JsonConvert.DeserializeObject<SomData>(#"{""aInt"":1, ""ALong"":2.2}");
Console.WriteLine(data.ALong); // output 2
var data2 = JsonConvert.DeserializeObject<SomData>(#"{""aInt"":1.2, ""ALong"":2}"); // exception
Console.WriteLine(data2.AInt);
internal class SomData
{
public int AInt { get; set; }
public long ALong { get; set; }
}
The answer is by design. we can see this discussion Error converting float value to integer in Web API #654. The author's answer was below.
Later versions of Json.NET throw an error when deserializing a floating-point value onto an integer property.
I would always use decimal when you are using floating-point numbers.
internal class SomData
{
public decimal AInt { get; set; }
public decimal ALong { get; set; }
}
EDIT
I had seen the source code of Json.Net
The Int value will will go into else part as below code from JsonTextReader in ReadType.ReadAsInt32
which might as author say by design.
ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out int value);
if (parseResult == ParseResult.Success)
{
numberValue = value;
}
else if (parseResult == ParseResult.Overflow)
{
throw ThrowReaderError("JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
else
{
throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
but let's see ReadType.ReadAsInt64 that else part is a lot of different between ReadAsInt32.
At First, it would get to else let value(object type) to store as float value as below code.
ParseResult parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out long value);
if (parseResult == ParseResult.Success)
{
numberValue = value;
numberType = JsonToken.Integer;
}
else if (parseResult == ParseResult.Overflow)
{
#if HAVE_BIG_INTEGER
string number = _stringReference.ToString();
if (number.Length > MaximumJavascriptIntegerCharacterLength)
{
throw ThrowReaderError("JSON integer {0} is too large to parse.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
numberValue = BigIntegerParse(number, CultureInfo.InvariantCulture);
numberType = JsonToken.Integer;
#else
throw ThrowReaderError("JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
#endif
}
else
{
if (_floatParseHandling == FloatParseHandling.Decimal)
{
parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out decimal d);
if (parseResult == ParseResult.Success)
{
numberValue = d;
}
else
{
throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
}
else
{
string number = _stringReference.ToString();
if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double d))
{
numberValue = d;
}
else
{
throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
}
numberType = JsonToken.Float;
}
Then the number will be convert to Int64 by JsonSerializerInternalReader.EnsureType
// this won't work when converting to a custom IConvertible
return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture);
so we can get long will not get execption but int will, not sure why ReadAsInt64 allow store as float but int was not.

unable to change the value of a property

I am currently improving my program that I posted on CR but I ran into a problem. I have a property called Total but when I try to set it to a value (0) it remains the same.
This is the property:
public class Player
{
private int total;
public int Total
{
get
{
total = 0;
foreach (int card in hand)
{
total += card;
}
return total;
}
set { this.total = value; }
}
}
And here is how I try to change it:
public class Game
{
private void CompareHands()
{
//This is just for testing
Console.WriteLine($"player total: {player1.Total}, is bust: {player1.Bust}");
Console.WriteLine($"house total: {house.Total}, is bust: {house.Bust}");
if (player1.Bust)
player1.Total = 0;
if (house.Bust)
house.Total = 0;
//this too
Console.WriteLine($"player total: {player1.Total}, is bust: {player1.Bust}");
Console.WriteLine($"house total: {house.Total}, is bust: {house.Bust}");
...
}
Also the Bust property if needed:
private readonly int blackjack = 21;
public bool Bust
{
get { return Bust = Total > blackjack; }
private set { }
}
Actually you're recalculating the total everytime you call the getter of your property.
A solution is to make the field total as Nullable<int> so if it is null, you do the logic you're doing actually otherwise return what is set in the field total.
public class Player
{
private int? total; // <- Nullable<int> here
public int Total
{
get
{
if(total.HasValue) // <- If value is set return that value.
{
return total.Value;
}
total = 0;
foreach (int card in hand)
{
total += card;
}
return total.Value;
}
set { this.total = value; }
}
}
If I were you I would separate the Total calculation and Bust a bit differently:
public class Player
{
public bool Bust { get; set; }
public int GetTotal()
{
if (Bust)
{
return 0;
}
var total = 0;
foreach (int card in hand)
{
total += card;
}
return total;
}
}
A few things to notice:
the calculation is done in a method not a property - i think this is a cleaner way since a property is supposed to be quite simple and not have any logic in it
include Bust in the GetTotal calculation and return 0 if Bust is set to true
always compute the total value, unless you have a very good reason to have a cached version of it
Hope this helps.

Implementation of RPROP fails when current partial derivative of error gradient equal to 0

I am currently implementing the RPROP algorithm and am finding it fails to work when solving the XOR problem. This seems to me to be because when you give the Neural Network the input values, 2 of the input neurons have an output of 0. Therefore when you calculate the partial derivative to the error rate of that neuron, you get a 0 value. This means when the RPROP algorithm runs, it works out the sign of the current partial derivative against the previous partial derivative and this says the sign is 0 correctly. Thus, the delta isn't calculated but the previous one is used with a sign change of the current partial derivative. This causes the update value to be 0 and therefore the algorithm fails.
I wondered if anyone could tell me what exactly I am doing wrong, as i have read over the algorithm and seen the encog implementation and am still struggling to solve this problem.
The error gradient is calculated for hidden layers as:
public void SetNeuronErrorGradient(Neuron neuron)
{
neuron.ErrorGradient = neuron.OutputSynapses.Sum(a => a.OutputNeuron.ErrorGradient * a.Weight) *
neuron.ActivationFunction.Derivative(neuron.LatestFedValueFromInputSynapses);
}
The error gradient of the output layer is calculated as:
public void SetNeuronErrorGradient(Neuron neuron, double target)
{
neuron.ErrorGradient = CalculateErrorForOutputAgainstTarget(neuron, target) *
neuron.ActivationFunction.Derivative(neuron.LatestFedValueFromInputSynapses);
}
The algorithm for RPROP is then implemented as follows, where a Synapse consists on an input neuron, output neuron, and weight and weight delta.:
public sealed partial class ResilientBackPropagationSynapseWeightCalculator : IUpdateSynapseWeights
{
private static ILogger Log => LoggerProvider.For<ResilientBackPropagationSynapseWeightCalculator>();
private readonly Dictionary<Synapse, double> synapseToPreviousPartialDerivative
= new Dictionary<Synapse, double>(SynapseEqualityComparer.Instance());
private readonly Dictionary<Synapse, double> synapseToPreviousDeltaWithoutDirection
= new Dictionary<Synapse, double>(SynapseEqualityComparer.Instance());
private ResilientBackPropagationSynapseWeightCalculator()
{}
public void CalculateAndUpdateInputSynapseWeights(Neuron neuron, ParallelOptions parallelOptions)
{
neuron.InputSynapses.ForEach(
synapse =>
{
var previousPartialDerivative = GetPreviousPartialDerivativeOfSynapse(synapse);
var currentPartialDerivative = synapse.OutputNeuron.ErrorGradient * synapse.InputNeuron.Output;
var weightDelta = CalculateSynapseWeightDelta(
synapse,
currentPartialDerivative,
previousPartialDerivative);
synapse.WeightDelta = weightDelta;
synapse.Weight = synapse.Weight + weightDelta;
});
}
private double GetPreviousPartialDerivativeOfSynapse(Synapse synapse)
{
if (synapseToPreviousPartialDerivative.TryGetValue(synapse, out var previousPartialDerivative))
{
return previousPartialDerivative;
}
synapseToPreviousPartialDerivative[synapse] = 0;
return 0;
}
private double CalculateSynapseWeightDelta(
Synapse synapse,
double currentPartialDerivative,
double previousPartialDerivative)
{
var errorGradientSign =
ResilientBackPropagationHelper.Sign(currentPartialDerivative * previousPartialDerivative);
double weightDelta;
if (errorGradientSign > 0)
{
weightDelta = ResilientBackPropagationHelper
.CalculateDeltaToContinueTowardsErrorGraidentMinimum(
synapse,
currentPartialDerivative,
synapseToPreviousDeltaWithoutDirection);
synapseToPreviousPartialDerivative[synapse] = currentPartialDerivative;
}
else if (errorGradientSign < 0)
{
weightDelta = ResilientBackPropagationHelper
.CalculateDeltaToRevertPreviousWeightAdjustment(
synapse,
currentPartialDerivative,
synapseToPreviousDeltaWithoutDirection);
synapseToPreviousPartialDerivative[synapse] = 0; //0 so no adjustment next iteration.
}
else
{
weightDelta = ResilientBackPropagationHelper
.CalculateDeltaDirection(
synapse,
currentPartialDerivative,
synapseToPreviousDeltaWithoutDirection);
synapseToPreviousPartialDerivative[synapse] = currentPartialDerivative;
}
return weightDelta;
}
public static ResilientBackPropagationSynapseWeightCalculator Create()
=> new ResilientBackPropagationSynapseWeightCalculator();
}
With the helper function class implemented as:
internal static class ResilientBackPropagationHelper
{
private const double NegativeWeightUpdateAmount = 0.5;
private const double PositiveWeightUpdateAmount = 1.2;
private const double MaximumWeightUpdate = 50.0;
private const double MinimumWeightUpdate = 1.0E-6;
private const double InitialUpdateValue = 0.1;
private const double ZeroTolerance = 0.00000000000000001d;
public static int Sign(double value)
{
if (Math.Abs(value) < ZeroTolerance)
{
return 0;
}
if (value > 0)
{
return 1;
}
return -1;
}
public static double CalculateDeltaToContinueTowardsErrorGraidentMinimum(
Synapse synapse,
double currentPartialDerivative,
Dictionary<Synapse, double> synapseToPreviousDeltaWithoutDirection)
{
if (synapseToPreviousDeltaWithoutDirection.TryGetValue(synapse, out var previousUpdateValue))
{
var delta = Math.Min(previousUpdateValue * PositiveWeightUpdateAmount, MaximumWeightUpdate);
synapseToPreviousDeltaWithoutDirection[synapse] = delta;
return Sign(currentPartialDerivative) * delta;
}
throw new InvalidOperationException($"You cannot increase a prevous delta is none is present.");
}
public static double CalculateDeltaToRevertPreviousWeightAdjustment(
Synapse synapse,
double currentPartialDerivative,
Dictionary<Synapse, double> synapseToPreviousDeltaWithoutDirection)
{
if (synapseToPreviousDeltaWithoutDirection.TryGetValue(synapse, out var previousUpdateValue))
{
var delta = Math.Max(previousUpdateValue * NegativeWeightUpdateAmount, MinimumWeightUpdate);
synapseToPreviousDeltaWithoutDirection[synapse] = delta;
return -synapse.WeightDelta;
}
throw new InvalidOperationException($"You cannot revert a previous change if none is known.");
}
public static double CalculateDeltaDirection(
Synapse synapse,
double currentPartialDerivative,
Dictionary<Synapse, double> synapseToPreviousDeltaWithoutDirection)
{
if (synapseToPreviousDeltaWithoutDirection.TryGetValue(synapse, out var previousUpdateValue))
{
return Sign(currentPartialDerivative) * previousUpdateValue;
}
synapseToPreviousDeltaWithoutDirection.Add(synapse, InitialUpdateValue);
return CalculateDeltaDirection(
synapse,
currentPartialDerivative,
synapseToPreviousDeltaWithoutDirection);
}
}
Any help as to where my logic is failing would be really appreciated as I have tried numerous ways of getting this to work now against the algorithm.
Many Thanks
Joe

Using Livecharts Constant Changes example want to assign a double variable from different class to Value Variable of ConstantChangesChart()

I want this Variable name Pressure assign to the Value Variable of Measurable Class.
public static float[] Pressure1 = new float[35000];
constantChangesChart CLass();
public partial class ConstantChangesChart : UserControl,
INotifyPropertyChanged
{
private double _axisMax;
private double _axisMin;
private double _trend;
double []cv=new double[]{1.2,3,4,5,2,6,7,8,9,0,1,1};
public ConstantChangesChart()
{
InitializeComponent();
//To handle live data easily, in this case we built a specialized type
//the MeasureModel class, it only contains 2 properties
//DateTime and Value
//We need to configure LiveCharts to handle MeasureModel class
//The next code configures MeasureModel globally, this means
//that LiveCharts learns to plot MeasureModel and will use this config every time
//a IChartValues instance uses this type.
//this code ideally should only run once
//you can configure series in many ways, learn more at
//http://lvcharts.net/App/examples/v1/wpf/Types%20and%20Configuration
var mapper = Mappers.Xy<MeasureModel>()
.X(model => model.DateTime.Ticks) //use DateTime.Ticks as X
.Y(model => model.Value); //use the value property as Y
// .Y(model => model.Value2);
//lets save the mapper globally.
Charting.For<MeasureModel>(mapper);
// Charting.For<Double>(mapper);
//the values property will store our values array
ChartValues = new ChartValues<MeasureModel>();
// ChartVal = new ChartValues<double>();
//lets set how to display the X Labels
DateTimeFormatter = value => new DateTime((long) value).ToString("mm:ss");
//cv[5]=1.2;
//AxisStep forces the distance between each separator in the X axis
AxisStep = TimeSpan.FromSeconds(1).Ticks;
//AxisUnit forces lets the axis know that we are plotting seconds
//this is not always necessary, but it can prevent wrong labeling
AxisUnit = TimeSpan.TicksPerSecond;
SetAxisLimits(DateTime.Now);
//The next code simulates data changes every 300 ms
IsReading = false;
DataContext = this;
}
public ChartValues<MeasureModel> ChartValues { get; set; }
public Func<double, string> DateTimeFormatter { get; set; }
public double AxisStep { get; set; }
public double AxisUnit { get; set; }
public static float[] Pressure1 = new float[35000];
public double AxisMax
{
get { return _axisMax; }
set
{
_axisMax = value;
OnPropertyChanged("AxisMax");
}
}
public double AxisMin
{
get { return _axisMin; }
set
{
_axisMin = value;
OnPropertyChanged("AxisMin");
}
}
public bool IsReading { get; set; }
private void Read()
{
var r = new Random();
while (IsReading)
{
Thread.Sleep(150);
var now = DateTime.Now;
_trend += r.Next(0, 10);
ChartValues.Add(new MeasureModel
{
DateTime = now,
Value = _trend,
// Value2=
Value 2=Pressure1;
});
but i am stuck in it.
my another class where i am storing coming data from serial port into this Pressure variable value of almost 1024 bytes.
for (int i = 0; i < 1024; i++)
{
if (gsb_read_block <= (gsb_no_of_blocks/2))
{
TempVal = (Int16)(response[x++] << 8);
TempVal |= response[x++];
TempValFloat = (float)((TempVal * 1.00f) / 100.0f);
Pressure1[(i + ((gsb_read_block - 1) * 1024))] = (float)Convert.ToDouble(TempValFloat.ToString("F2"));
//Pressure1[(i+((gsb_read_block-1)*1024))] =(UInt16) TempVal;
}
else
{
TempVal = (Int16)(response[x++] << 8);
TempVal |= response[x++];
TempValFloat = (float)((TempVal * 1.00f) / 100.0f);
Pressure2[(i + (((UInt16)(gsb_read_block / 2) - 1) * 1024))] = (float)Convert.ToDouble(TempValFloat.ToString("F2"));
//Pressure2[(i + (((UInt16)(gsb_read_block/2) - 1) * 1024))] = (UInt16)TempVal;
}
So i want to Represent Pressure Value on to y-axis of a Chart with respect to the Time on X axis.

Elegant way to validate values

I have a class with many fields which represents different physical values.
class Tunnel
{
private double _length;
private double _crossSectionArea;
private double _airDensity;
//...
Each field is exposed using read/write property. I need to check on setter that the value is correct and generate exception otherwise. All validations are similar:
public double Length
{
get { return _length; }
set
{
if (value <= 0) throw new ArgumentOutOfRangeException("value",
"Length must be positive value.");
_length = value;
}
}
public double CrossSectionArea
{
get { return _crossSectionArea; }
set
{
if (value <= 0) throw new ArgumentOutOfRangeException("value",
"Cross-section area must be positive value.");
_crossSectionArea = value;
}
}
public double AirDensity
{
get { return _airDensity; }
set
{
if (value < 0) throw new ArgumentOutOfRangeException("value",
"Air density can't be negative value.");
_airDensity = value;
}
}
//...
Is there any elegant and flexible way to accomplish such validation?
Assuming you want this sort of behaviour, you might consider some helper methods, e.g.
public static double ValidatePositive(double input, string name)
{
if (input <= 0)
{
throw new ArgumentOutOfRangeException(name + " must be positive");
}
return input;
}
public static double ValidateNonNegative(double input, string name)
{
if (input < 0)
{
throw new ArgumentOutOfRangeException(name + " must not be negative");
}
return input;
}
Then you can write:
public double AirDensity
{
get { return _airDensity; }
set
{
_airDensity = ValidationHelpers.ValidateNonNegative(value,
"Air density");
}
}
If you need this for various types, you could even make it generic:
public static T ValidateNonNegative(T input, string name)
where T : IComparable<T>
{
if (input.CompareTo(default(T)) < 0)
{
throw new ArgumentOutOfRangeException(name + " must not be negative");
}
return input;
}
Note that none of this is terribly i18n-friendly...
All depends what technology you are using - if you're under MVC you can use Attributes, like this;
http://msdn.microsoft.com/en-us/library/ee256141(v=vs.98).aspx
Here's my version, it's a bit cleaner than Jon's version in some respects:
interface IValidator <T>
{
bool Validate (T value);
}
class IntValidator : IValidator <int>
{
public bool Validate (int value)
{
return value > 10 && value < 15;
}
}
class Int2Validator : IValidator<int>
{
public bool Validate (int value)
{
return value > 100 && value < 150;
}
}
struct Property<T, P> where P : IValidator<T>, new ()
{
public T Value
{
set
{
if (m_validator.Validate (value))
{
m_value = value;
}
else
{
Console.WriteLine ("Error validating: '" + value + "' is out of range.");
}
}
get { return m_value; }
}
T m_value;
static IValidator<T> m_validator=new P();
}
class Program
{
static void Main (string [] args)
{
Program
p = new Program ();
p.m_p1.Value = 9;
p.m_p1.Value = 12;
p.m_p1.Value = 25;
p.m_p2.Value = 90;
p.m_p2.Value = 120;
p.m_p2.Value = 250;
}
Property<int, IntValidator>
m_p1;
Property<int, Int2Validator>
m_p2;
}
Try to use such a method:
public void FailOrProceed(Func<bool> validationFunction, Action proceedFunction, string errorMessage)
{
// !!! check for nulls, etc
if (!validationFunction())
{
throw new ArgumentOutOfRangeException(errorMessage);
}
proceedFunction();
}
Yes, by creating your own validation attributes.
Read this article: Business Object Validation Using Attributes in C#
I will have the decency of NOT copying it here :)
Using the Validator function I mentioned in my comment above, I'd do something like this (untested code):
void textBox_Changed(object sender, EventArgs e) {
submitButton.Enabled = validator();
}
bool validator() {
const string NON_POSITIVE = "Value must be greater than Zero";
bool result = false;
string controlName = "Length";
try {
_length = Convert.ToDouble(txtLength.Text);
if (_length <= 0) throw new Exception(NON_POSITIVE);
controlName = "Cross Section Area";
_crossSectionArea = Convert.ToDouble(txtCrossSectionArea.Text);
if (_crossSectionArea <= 0) throw new Exception(NON_POSITIVE);
controlName = "Air Density";
_airDensity = Convert.ToDouble(txtAirDensity.Text);
if (_airDensity <= 0) throw new Exception(NON_POSITIVE);
result = true; // only do this step last
} catch (Exception err) {
MessageBox.Show(controlName + " Error: " + err.Message, "Input Error");
}
return result;
}
John Skeet probably has a better way, but this works. :)
You can achieve this using classes from System.ComponentModel.DataAnnotations
class Tunnel
{
[Range(0, double.MaxValue, ErrorMessage = "Length must be positive value.")]
public double Length { get; set; }
}
Validation:
var tunnel = new Tunnel { Length = 0 };
var context = new ValidationContext(tunnel, null, null);
Validator.ValidateObject(tunnel, context, true);
Also you can implement your own validation attributes overriding ValidationAttribute class

Categories