Java自定义数字接口-平方根

Java自定义数字接口-平方根,java,numerical-methods,Java,Numerical Methods,问题是在通用数值接口中定义平方根算法问题的策略方法。我知道在不同的条件下,解决这个问题的算法是存在的。我对以下算法感兴趣: 仅使用选定的函数解决问题 不在乎被操纵的对象是整数、浮点还是其他,只要这些对象可以被添加、多重化和对置 如果输入为完全平方,则返回精确解 由于区分的微妙性,为了清晰起见,我将以非常详细的方式定义这个问题。当心墙上的文字 假设有一个Java接口常量,其中包含以下抽象方法,我们将其称为基函数: C添加(C a) C减法(ca) C乘(ca) C[]分隔符和维护符(cb)

问题是在通用数值接口中定义平方根算法问题的策略方法。我知道在不同的条件下,解决这个问题的算法是存在的。我对以下算法感兴趣:

  • 仅使用选定的函数解决问题
  • 不在乎被操纵的对象是整数、浮点还是其他,只要这些对象可以被添加、多重化和对置
  • 如果输入为完全平方,则返回精确解
由于区分的微妙性,为了清晰起见,我将以非常详细的方式定义这个问题。当心墙上的文字


假设有一个Java接口
常量
,其中包含以下抽象方法,我们将其称为基函数:

  • C添加(C a)
  • C减法(ca)
  • C乘(ca)
  • C[]分隔符和维护符(cb)
  • C additiveInverse()
  • C乘法逆()
  • C additiveIdentity()
  • C乘法实体()
  • int比较(C arg1)
不知道C是表示整数还是浮点,这也不一定与下面的讨论相关

仅使用这些方法可以创建有关数字的一些数学算法的
静态
默认
实现:例如,
除法和余数(cb)
比较(C arg1)允许为更大的公约数、贝佐特标识等创建算法

现在假设我们的接口有一个用于求幂的
默认方法:

public default C pow(int n){
    if(n <  0) return this.additiveInverse().pow(-n);
    if(n == 0) return additiveIdentity();
    int m = n;
    C output = this;
    while(m > 1)
        {
        if(m%2 == 0)  output = output.multiply(output);
        else          output = this.multiply(output.multiply(output));
        m = m/2;
        }
    return output;
    }
公共默认C功率(int n){
如果(n<0),则返回此.additiveInverse().pow(-n);
如果(n==0)返回additiveIdentity();
int m=n;
C输出=此;
而(m>1)
{
如果(m%2==0)输出=output.multiply(输出);
else output=this.multiply(输出.multiply(输出));
m=m/2;
}
返回输出;
}
目标是定义两个名为
C root(int n)
C maximumerroallowed()
default
方法,以便:

  • x.equals(y.pow(n))
    表示
    x.root(n).equals(y)
  • C根(int-n)实际上是实现的仅使用基本函数和从基本函数创建的方法
    
  • 该接口仍然可以应用于任何类型的数字,包括但不限于整数和浮点
  • this.root(n).pow(n).compareTo(maximumerroallowed())==-1
    对于所有
    this
    这样
    this.root(n)=空
    ,即任何最终近似值的误差小于
    C maximumErrorAllowed()

可能吗?如果是的话,计算复杂度的评估方法和内容是什么?

我花了一些时间为Java开发一个自定义数字接口,这非常困难——这是我使用Java时最令人失望的经历之一

问题是你必须从头开始——你不能真正重用Java中的任何东西,所以如果你想实现int、float、long、biginger、rational、Complex和Vector,你必须为每个类自己实现所有方法,然后不要指望数学包会有多大帮助

实现“组合”类,比如由两种“通用”浮点类型组成的“Complex”类,或者由两种通用整数类型组成的“Rational”类,就变得特别糟糕

数学运算符是正确的——这可能特别令人沮丧

我让它工作得相当好的方法是用Java实现类,然后用Groovy编写一些更高级的东西。如果操作命名正确,Groovy就可以选择它们,就像您的类实现“.plus()”一样,那么Groovy将允许您执行instance1+instance2

IIRC由于是动态的,Groovy通常能够很好地处理跨类片段,比如说,如果你说的是Complex+Integer,你可以提供从整数到复数的转换,Groovy会将Integer升级到复数来执行操作并返回复数

Groovy与Java是非常可互换的,您通常只需重命名一个Java类“.Groovy”并编译它,它就会工作,所以这是一个非常好的折衷方案

这是很久以前的事了,现在你可能会在你的“数字”接口中使用Java 8的默认方法,这可能会使实现一些类变得更容易,但可能没有帮助。我必须再试一次才能找到答案,而且我不确定我是否想重新打开那些可能的蠕虫

可能吗?如果是,如何进行

理论上,是的。对于
root()
,有一些近似算法,例如。但是,您可能会遇到精度方面的问题,您可能希望逐个解决(即使用整数查找表)。因此,我建议不要在接口中使用默认实现

计算复杂性的估计是什么

这也取决于您的数字类型,并且取决于您的精度。对于整数,您可以使用查找表创建一个实现,其复杂性为O(1)


如果您想对操作本身的复杂性有一个更好的答案,您可能需要检查。

可能很难有效地实现
this==this.pow(n).root(n)
;您是否满意
this.equals(this.pow(n).root(n))
this==this.pow(n).root(n)
对于int和double,如果
this
为负数且
n
为2的倍数,则int和double都为
假。那是expec吗