我正在尝试使用动态数学运算符处理二维数组。
这是有问题的方法:
public float[,] Calculate(int[,] a, int[,] b, Func<int,int,float> compute)
{
int columns = a.GetLength(0);
int rows = a.GetLength(1);
float[,] result = new float[columns,rows];
for(int i = 0; i < columns; i++)
{
for(int j = 0; j < rows; j++)
{
result[i,j] = compute(a[i,j], b[i,j]);
}
}
return result;
}
此方法的调用如下:
int[,] a = new int[2,3] { {2, 6, 19}, {3, -4, 25}};
int[,] b = new int[2,3] { {12, -2, 11}, {1, -11, 0}};
//1
float[,] c = Calculate(a, b, (x,y) => (x+y));
//2
float[,] c = Calculate(a, b, (x,y) => (x-y));
//3
float[,] c = Calculate(a, b, (x,y) => (x*y));
//4
float[,] c = Calculate(a, b, (x,y) => (x/y));
现在,虽然版本1到3完美无缺,但版本4迟早会抛出异常。 现在,处理此问题的一种方法是使用try catch块:
try
{
result[i,j] = compute(a[i,j], b[i,j]);
}
catch(DivideByZeroException ex)
{
result[i,j] = 0;
}
这看起来像我使用try catch进行流控制而我宁愿避免它(而且结果是错误的)。有没有办法在函数调用中检查除法运算符,如果运算符是/
,检查第二个数组是否包含0并且只返回null?
答案 0 :(得分:2)
通常的流量控制怎么样?一个if
声明?
float[,] c;
if (b != 0)
c = Calculate(a, b, (x,y) => (x/y));
else
c = 0;
答案 1 :(得分:1)
这可能看起来有点奇怪的解决方案但是,您可以使用随机数测试您的函数并检查结果,如果结果总是1
那么这意味着它是一个除法运算:
static bool IsDivision(Func<int, int, float> func)
{
var rnd = new Random();
return Enumerable.Range(0, 10)
.Select(x => rnd.Next(100))
.All(x => Math.Abs(func(x, x) - 1) < 0.000001);
}
然后,在执行操作之前,您可以将func传递给此方法并执行适当的操作:
if(IsDivision(compute) && b.OfType<int>().Any(x => x == 0)) return null;
但我同意这不是一个很好的解决方案,例如这不适用于(x,y) => 1
,但我认为你知道你在做什么,你不会将那种怪异的表达式传递给你的函数:)