说我有一个等式:
out = Math.exp(x);
其中x
是double
。
说我做了10,000次,所以我把它扔进了一个函数:
public double doMath(double x) {
return Math.exp(x);
}
够容易。我可以传递任何标量:
double in = 1.1234;
out = doMath(in);
// Outputs something like: 1.1313368652
但是尝试将矢量传递给它(1D数组,2D数组等等......)会导致各种问题:
double[] in = {0.1234, 5.6789};
out = doMath(in);
// Outputs something like: IT DOESN'T OUTPUT! CRASH CRASH CRASH!
我想要的是能够传递任何双(标量,1D,2D,3D等)并返回与输入相同的大小,在通过等式后,将算法应用于每个元素
测试用例
double in = 0.1234;
/*
1.1313368652
*/
double[] in = {0.1234, 5.6789};
/*
[ 1.1313368652, 292.6273627191 ]
*/
double[][] in = {{0.1234, 5.6789},
{0.9876, 5.4321}};
/*
[ [ 1.1313368652, 292.6273627191 ]
[ 2.6847832542, 228.6288622608 ] ]
*/
double[][][] in = {{{0.1234, 5.6789}, {0.9876}},
{{5.4321}},
{{0}, {1}}};
/*
[ [ [ 1.1313368652 292.6273627191 ] [ 2.6847832542 ] ]
[ [ 228.6288622608 ] ]
[ [ 1 ] [ 2.7182818285 ] ] ]
*/
我现在唯一的方法是使用overloading:
public double doMath(double x)
public double[] doMath(double[] x)
public double[][] doMath(double[][] x)
public double[][][] doMath(double[][][] x)
但这很乏味。可以编写单个函数来接受任何参数维度,并返回类似于我提供的示例吗?
也许有一个名字,我只是不知道?这些都只是数组,但我正在对它们进行处理(并对它们进行其他操作),就像它们是不同维度的矩阵一样。
编辑#1 - 另外......
我尝试过类似的事情:
public double doMath(int... x)
它适用于标量和1D,但没有更高的尺寸。
编辑#2
是否可以编写一个自定义类,自动为多个函数处理它?</ p>
例如,假设我有三种不同的功能:
public mysteryClass firstFunct(mysteryClass x) {
return Math.pow(x, 2);
}
public mysteryClass secondFunct(mysteryClass x) {
return Math.exp(x);
}
public mysteryClass thirdFunct(mysteryClass x) {
return (1 + x) / 2;
}
每个函数都可以使用 - 按 - 任意数量的维度?然后mysteryClass
会自动递归地运行每个元素通过函数,而不必修改函数或手动循环遍历每个元素?不确定对象是否可以知道如何使用它,并相应地进行调整。
提前致谢。
答案 0 :(得分:2)
我不知道有这样做的内置方式,但我得到了一些像这样的工作:
public static Object applyAll(Object x) {
if (x instanceof Double) {
return doFunc((Double) x);
}
else if (x instanceof Object[]) {
List<Object> result = new ArrayList<>();
for (Object element : (Object[])x) {
result.add(applyAll(element));
}
return result.toArray(new Object[0]);
}
else {
throw new RuntimeException("Unexpected class: " + x.getClass());
}
}
applyAll
适用于Double
或数组,如果它是一个数组,它会在元素上递归调用并构建结果数组。最终结果是最终结果的数组结构与最外层参数的结构相匹配。但是,如果任何元素不是Double
或数组,则会抛出异常。 doFunc
是一种接受double
或Double
参数的方法,并返回double
或Double
。您可以轻松地将函数作为参数传递(使用Java 8功能接口),而不是要求doFunc
定义。在您的示例中,doFunc
会在其参数上返回Math.exp
。
这可能不是最好的代码,但它有效。您不需要构建列表然后转换为数组,因为数组的大小已经知道了。但是,我没有尝试过改进它。您可以根据需要自由改进或修改它。
答案 1 :(得分:2)
class IncompatibleMultiDoubleException extends RuntimeException {
}
class MultiDouble {
private double[] data;
private int[] dims;
public MultiDouble(int...dimensions) {
dims = dimensions;
int tot = 1;
for (int d : dimensions) {
tot *= d;
}
data = new double[tot];
}
// multiply matrix by value
void cMul(double c) {
for (int i=0; i<data.length; i++) {
data[i] *= c;
}
}
// add two matrices together
void add(MultiDouble other) {
for(int i=0; i<other.dims.length; i++) {
if (dims[i] != other.dims[i]) {
throw new IncompatibleMultiDoubleException();
}
}
}
// return the index in the data array corrisponding to the
// given multidim coordinates
private int index(int...coords) {
int res = 0;
for(int i=0; i<coords.length; i++) {
int tmp = coords[i];
for(int j=i+1; j<coords.length; j++) {
tmp *= dims[j];
}
res += tmp;
}
return res;
}
public void set(double value, int...coords) {
data[index(coords)] = value;
}
public double get(int...coords) {
return data[index(coords)];
}