Skip to content

Commit

Permalink
Issue #22 - more numerical values are now converted to a safe common …
Browse files Browse the repository at this point in the history
…type to correct division of double / decimal, etc.
  • Loading branch information
bijington committed Jun 7, 2018
1 parent 3814780 commit dfc83cd
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 25 deletions.
49 changes: 41 additions & 8 deletions Source/CSharp/Expressive/Expressive.Tests/ExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,6 @@ public void SimpleDecimalSubtraction()
Assert.AreEqual(2.3M, value);
}

[TestMethod, ExpectedException(typeof(ExpressiveException), "Operator '-' can't be applied to operands of types 'decimal' and 'double'")]
public void ShouldNotSubtractDoubleAndDecimal()
{
var expression = new Expression("1.8 - Abs([var1])");

object value = expression.Evaluate(new Dictionary<string, object> { { "var1", 0.2 } });
}

[TestMethod]
public void ShouldHandleUnarySubtraction()
{
Expand Down Expand Up @@ -937,5 +929,46 @@ public void ShouldHandlePartiallyMatchingCustomFunctionNames()
}

#endregion

[TestMethod]
public void ShouldHandleBugTwentyTwo()
{
// Not working
//[myDouble]*5
//[myDouble]* pow(5.5,2)
//[myDouble]+5.5

var arguments = new Dictionary<string, object>
{
["myDouble"] = 4.0,
["myFloat"] = 4.0f
};

var expression = new Expression("[myDouble]*5");
Assert.AreEqual(20, (double)expression.Evaluate(arguments));

expression = new Expression("[myDouble]*Pow(5.5,2)");
Assert.AreEqual(121, (double)expression.Evaluate(arguments));

expression = new Expression("[myDouble]+5.5");
Assert.AreEqual(9.5M, (decimal)expression.Evaluate(arguments));

// Not working
//[myDouble]*5.5
expression = new Expression("[myDouble]*5.5");
Assert.AreEqual(22M, (decimal)expression.Evaluate(arguments));

expression = new Expression("[myDouble]-5.5");
Assert.AreEqual(-1.5M, (decimal)expression.Evaluate(arguments));

expression = new Expression("[myDouble]+5.5");
Assert.AreEqual(9.5M, (decimal)expression.Evaluate(arguments));

expression = new Expression("[myDouble]/2.0");
Assert.AreEqual(2.0M, (decimal)expression.Evaluate(arguments));

expression = new Expression("[myFloat]/2.0");
Assert.AreEqual(2.0M, (decimal)expression.Evaluate(arguments));
}
}
}
39 changes: 22 additions & 17 deletions Source/CSharp/Expressive/Expressive/Helpers/Numbers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ internal static object Add(object a, object b)
case TypeCode.UInt16: return (UInt64)a + (UInt16)b;
case TypeCode.Int32: throw new InvalidOperationException("Operator '+' can't be applied to operands of types 'ulong' and 'int'");
case TypeCode.UInt32: return (UInt64)a + (UInt32)b;
case TypeCode.Int64: throw new InvalidOperationException("Operator '+' can't be applied to operands of types 'ulong' and 'ulong'");
case TypeCode.Int64: throw new InvalidOperationException("Operator '+' can't be applied to operands of types 'ulong' and 'long'");
case TypeCode.UInt64: return (UInt64)a + (UInt64)b;
case TypeCode.Single: return (UInt64)a + (Single)b;
case TypeCode.Double: return (UInt64)a + (Double)b;
Expand Down Expand Up @@ -256,6 +256,7 @@ internal static object Add(object a, object b)

return null;
}

internal static object Divide(object a, object b)
{
if (a == null || b == null)
Expand Down Expand Up @@ -428,7 +429,7 @@ internal static object Divide(object a, object b)
case TypeCode.UInt64: return (Single)a / (UInt64)b;
case TypeCode.Single: return (Single)a / (Single)b;
case TypeCode.Double: return (Single)a / (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '/' can't be applied to operands of types 'float' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) / (Decimal)b;
}
break;

Expand All @@ -445,7 +446,7 @@ internal static object Divide(object a, object b)
case TypeCode.UInt64: return (Double)a / (UInt64)b;
case TypeCode.Single: return (Double)a / (Single)b;
case TypeCode.Double: return (Double)a / (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '/' can't be applied to operands of types 'double' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) / (Decimal)b;
}
break;

Expand All @@ -460,15 +461,16 @@ internal static object Divide(object a, object b)
case TypeCode.UInt32: return (Decimal)a / (UInt32)b;
case TypeCode.Int64: return (Decimal)a / (Int64)b;
case TypeCode.UInt64: return (Decimal)a / (UInt64)b;
case TypeCode.Single: throw new InvalidOperationException("Operator '/' can't be applied to operands of types 'decimal' and 'float'");
case TypeCode.Double: throw new InvalidOperationException("Operator '/' can't be applied to operands of types 'decimal' and 'double'");
case TypeCode.Single: return (Decimal)a / Convert.ToDecimal(b);
case TypeCode.Double: return (Decimal)a / Convert.ToDecimal(b);
case TypeCode.Decimal: return (Decimal)a / (Decimal)b;
}
break;
}

return null;
}

internal static object Multiply(object a, object b)
{
if (a == null || b == null)
Expand Down Expand Up @@ -641,7 +643,7 @@ internal static object Multiply(object a, object b)
case TypeCode.UInt64: return (Single)a * (UInt64)b;
case TypeCode.Single: return (Single)a * (Single)b;
case TypeCode.Double: return (Single)a * (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '*' can't be applied to operands of types 'float' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) * (Decimal)b;
}
break;

Expand All @@ -658,7 +660,7 @@ internal static object Multiply(object a, object b)
case TypeCode.UInt64: return (Double)a * (UInt64)b;
case TypeCode.Single: return (Double)a * (Single)b;
case TypeCode.Double: return (Double)a * (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '*' can't be applied to operands of types 'double' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) * (Decimal)b;
}
break;

Expand All @@ -673,15 +675,16 @@ internal static object Multiply(object a, object b)
case TypeCode.UInt32: return (Decimal)a * (UInt32)b;
case TypeCode.Int64: return (Decimal)a * (Int64)b;
case TypeCode.UInt64: return (Decimal)a * (UInt64)b;
case TypeCode.Single: throw new InvalidOperationException("Operator '*' can't be applied to operands of types 'decimal' and 'float'");
case TypeCode.Double: return (Decimal)a * Convert.ToDecimal(b);//throw new InvalidOperationException("Operator '*' can't be applied to operands of types 'decimal' and 'double'");
case TypeCode.Single: return (Decimal)a * Convert.ToDecimal(b);
case TypeCode.Double: return (Decimal)a * Convert.ToDecimal(b);
case TypeCode.Decimal: return (Decimal)a * (Decimal)b;
}
break;
}

return null;
}

internal static object Subtract(object a, object b)
{
if (a == null || b == null)
Expand Down Expand Up @@ -871,7 +874,7 @@ internal static object Subtract(object a, object b)
case TypeCode.UInt64: return (Single)a - (UInt64)b;
case TypeCode.Single: return (Single)a - (Single)b;
case TypeCode.Double: return (Single)a - (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '-' can't be applied to operands of types 'float' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) - (Decimal)b;
}
break;

Expand All @@ -888,7 +891,7 @@ internal static object Subtract(object a, object b)
case TypeCode.UInt64: return (Double)a - (UInt64)b;
case TypeCode.Single: return (Double)a - (Single)b;
case TypeCode.Double: return (Double)a - (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '-' can't be applied to operands of types 'double' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) - (Decimal)b;
}
break;

Expand All @@ -903,8 +906,8 @@ internal static object Subtract(object a, object b)
case TypeCode.UInt32: return (Decimal)a - (UInt32)b;
case TypeCode.Int64: return (Decimal)a - (Int64)b;
case TypeCode.UInt64: return (Decimal)a - (UInt64)b;
case TypeCode.Single: throw new InvalidOperationException("Operator '-' can't be applied to operands of types 'decimal' and 'float'");
case TypeCode.Double: throw new InvalidOperationException("Operator '-' can't be applied to operands of types 'decimal' and 'double'");
case TypeCode.Single: return (Decimal)a - Convert.ToDecimal(b);
case TypeCode.Double: return (Decimal)a - Convert.ToDecimal(b);
case TypeCode.Decimal: return (Decimal)a - (Decimal)b;
}
break;
Expand Down Expand Up @@ -1085,7 +1088,7 @@ internal static object Modulus(object a, object b)
case TypeCode.UInt64: return (Single)a % (UInt64)b;
case TypeCode.Single: return (Single)a % (Single)b;
case TypeCode.Double: return (Single)a % (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '%' can't be applied to operands of types 'float' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) % (Decimal)b;
}
break;

Expand All @@ -1102,7 +1105,7 @@ internal static object Modulus(object a, object b)
case TypeCode.UInt64: return (Double)a % (UInt64)b;
case TypeCode.Single: return (Double)a % (Single)b;
case TypeCode.Double: return (Double)a % (Double)b;
case TypeCode.Decimal: throw new InvalidOperationException("Operator '%' can't be applied to operands of types 'double' and 'decimal'");
case TypeCode.Decimal: return Convert.ToDecimal(a) % (Decimal)b;
}
break;

Expand All @@ -1117,15 +1120,16 @@ internal static object Modulus(object a, object b)
case TypeCode.UInt32: return (Decimal)a % (UInt32)b;
case TypeCode.Int64: return (Decimal)a % (Int64)b;
case TypeCode.UInt64: return (Decimal)a % (UInt64)b;
case TypeCode.Single: throw new InvalidOperationException("Operator '%' can't be applied to operands of types 'decimal' and 'float'");
case TypeCode.Double: throw new InvalidOperationException("Operator '%' can't be applied to operands of types 'decimal' and 'decimal'");
case TypeCode.Single: return (Decimal)a % Convert.ToDecimal(b);
case TypeCode.Double: return (Decimal)a % Convert.ToDecimal(b);
case TypeCode.Decimal: return (Decimal)a % (Decimal)b;
}
break;
}

return null;
}

internal static object Max(object a, object b)
{
a = ConvertIfString(a);
Expand Down Expand Up @@ -1166,6 +1170,7 @@ internal static object Max(object a, object b)

return null;
}

internal static object Min(object a, object b)
{
a = ConvertIfString(a);
Expand Down

0 comments on commit dfc83cd

Please sign in to comment.