关于VC6中添加函数库

关于VC6中添加函数库,第1张

extern "C"

{

__declspec(dllexport)

int WINAPI icePub_bigIntegerCalculate(char strArithmetic,char strResult);

}

#pragma comment(lib,"icePubDlllib")

char strResult[1024];

icePub_bigIntegerCalculate("12345+876154321",strResult);

AfxMessageBox(strResult);

icePub_bigIntegerCalculate("1234567719012345677190-8176154321",strResult);

AfxMessageBox(strResult);

icePub_bigIntegerCalculate("1357986421",strResult);

AfxMessageBox(strResult);

icePub_bigIntegerCalculate("1234567719/112233",strResult);

AfxMessageBox(strResult);

不可变类是指其实例不可被修改的类。 每个实例中包含的所有信息都必须在创建该实例的时候就提供,并在对象的整个声明周期内固定不变 。Java平台类库种包含许多不可变的类,其中有String、基本类型的包装类、BigInteger和BigDecimal。存在不可变类有许多理由: 不可变的类比可变类更加易于设计、实现和使用。它们不容易出错,且更加安全

为了使类成为不可变、要遵循下面五条规则:

1、 不要提供任何会修改对象状态的方法 (也称为设值方法)。

2、 保证类不会被扩展 。这样就可以防止粗心或者恶意的子类假装对象的状态已经改变,从而破坏该类的不可变类。为了防止子类化,一般的做法是声明这个类成为final的,但是后面的我们还会讨论其他的做法。

3、 声明所有的域都是final的 。通过系统的强制方式可以 清楚地表明你的意图 。而且,如果一个指向新创建实例地引用在缺乏同步机制地情况下,从一个线程被传递到另一个线程,就必须确保正确的行为,正如内存模型中所述。

4、 声明所有的域都为私有的 这样可以防止客户端获得访问被域引用的可变对象的权限 ,并防止客户端直接修改这些对象。虽然从技术上讲,允许不可变的类具有公有的final域,只要这些域包含基本类型的值或者指向不可变对象的引用, 但是不建议这样做,因为这样会使得再以后的版本中无法再改变内部的表示法 (详见第15条和第16条)。

5、 确保对于任何可变组件的互斥访问 。如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用,并且, 永远不要用客户端提供的对象引用来初始化这样的域,也不要从任何方法中返回该对象。在构造器、访问方法和readObject方法(详见第88条)中请使用保护性拷贝技术 (详见第50条)。

前面条目中的许多例子都是不可变的,其中一个例子是第11条中的PhoneNumber,他针对每个属性都有访问方法,但是没有对应的设置方法。下面稍微复杂点的例子:

这个类表示一个复数(complex number,具有实部和虚部)。除了标准的Object方法之外,它还提供了针对实部和虚部的访问方法,以及4种基本的算术运算:加法、减法、乘法和除法。 注意这些算术运算如何创建并返回新的Complex实例,而不是修改这个实例 。大多数重要的不可变都使用了这种模式。他被称之为函数的方法,因为这些方法返回了一个函数的结果,这些函数对 *** 作数进行运算但并不修改它。与之相对应的更常见的是过程或者命令式的方法,使用这些方法时,将一个过程作用在它们的 *** 作数上,会导致它的状态发生改变。注意,这些方法名称都是介词(如plus),而不是动词(如add)。这是为了强调该方法不会改变对象的值。BigInteger类的BigDecimal类由于没有遵守这一命名习惯,就导致了许多用法错误。

如果你对函数方式的做法还不太熟悉,可能会觉得它显得不太自然,但是它带来了不可变性,具有许多优点。 不可变对象比较简单 。不可变对象可以只有一种状态, 即被创建时的状态 。如果你能够确保所有的构造器都建立了这个类的约束关系,就可以确保这些约束关系在整个生命周期内永远不再发生变化,你和使用这个类的程序员都无须再做额外的工作来维护这些约束关系。另一方面,可变对象可以有任意复杂的状态空间。如果文档中没有为设值方法所执行的状态转换提供精确的描述,要可靠地使用可变类时非常困难地,甚至是不可能的。

不可变对象本质上是线程安全的,它们不要求同步 。当多个线程并发访问这样的对象时,它们不会遭到破坏。这无疑是获得了线程安全最容易的办法。实际上,没有任何线程会注意到其他线程对不可变对象的影响。所以, 不可变对象可以被自由地共享 。不可变类应该充分利用这种优势,鼓励客户端尽可能地重用现有地实例。要做到这一点,一个很简单地办法就是:对于频繁用到的值,为它们提供公有地静态final常量。例如,Complex类会提供下面地常量:

这种方法可以进一步扩展。不可变的类可以提供静态工厂(详见第1条),它们把频繁被请求的实例缓存起来,从而当现有的实例可以符合请求的时候。就不必创建新的实例。所有基本类型的包装类和BigInteger都有这样的静态工厂。使用静态工厂也使得客户端之间可以共享现有的实例,而不是创建新的实例,从而降低内存占用和垃圾回收器的成本,在设计新的类时,选择用静态工厂代替公有的构造器可以让你以后有添加缓存的灵活性,而不必影响客户端。

”不可变对象可以被自由的共享“导致的结果是,永远不需要进行保护性拷贝(详见第50条)。实际上,你根本无须做任何拷贝,因为这些拷贝始终等于原始的对象。因此,你不需要,也不应该为不可变的类提供clone方法或者拷贝构造器(详见第13条)。这一点再Java平台的早期并不好理解,所以String类仍然具有拷贝构造器,但是应该尽量少用它(详见第6条)。

不仅可以共享不可变对象,甚至也可以共享它们的内部信息 。例如,BigInteger类内部使用了符号数值表示法。符号用一个int类型的值来表示,数值则用一个int数组来表示。negate方法产生一个新的BigInteger,其中数值是一样的,符号则是相反的。它并不需要拷贝数组,新建的BigInetger也指向原始实例中的同一个内部数组。

不可变对象为其他对象提供了大量的构件 ,无论是可变的还是不可变的对象。如果知道一个复杂对象内部的组件对象不会改变,要维护它的不变性约束是比较容易的。这条原则的一种特例在于,不可变对象构成了大量的映射值(map key)和集合元素(set element);一旦不可变对象进入映射(map)或者集合(set)中,尽管这破坏了映射值或者集合的不变性约束,但是也不用担心它们的值会发生变化。

不可变对象无偿的提供了失败的原子性 (详见第76条),它们的状态永远不变,因此不存在临时不一致的可能性。

不可变对象真正唯一的缺点是,对于每个不同的值都需要一个单独的对象 。创建这些对象的单价可能很高,特别是大型的对象。例如,假设你有一个上百万为的BigInteger,想要改变它的低位:

flipBit方法创建了一个新的BigInteger实例,也有上百位长,它与原来的对象只差一位。这项 *** 作所消耗的时间和空间与BigInteger的成正比。我们拿它与javautilBitSet比较。与BigInteger类似,BitSet代表一个任意长度的位序列,但是与BigInteger不同的是,BitSet是可变的。BitSet类提供了一个方法,允许在固定的时间内改变”百万位“实例中单个位的状态:

如果你执行一个多步骤的 *** 作,并且每一个步骤都会产生一个新的对象,除了最后的结果之外,其他的对象最终都会被丢弃,此时性能问题就会显露出来。处理这种问题有两种办法。第一种,先猜测一下经常会用到哪些多步骤的 *** 作,然后将它们作为基本类型提供。如果某个多步骤 *** 作已经作为基本类型提供。例如:BigInteger有包级私有的可变”配套类“,它的 用途是加速诸如”模指数“这样的多步骤 *** 作。由于前面提到的诸多原因,使用可变的配套类比使用BigInteger要困难得多,但幸运的是,你并不需要这样做。因为BigInteger的实现者已经替你完成了所有的困难工作。

如果能够精确的预测出客户端将要在不可变的类上执行哪些复杂的多阶段 *** 作,这种包级私有的可变配套类的方法就可以工作地很好,如果无法预测,最好地办法是提供一个公有地可配套类。在Java平台类库中,这种方法地主要例子是String类,它的可配套类是StringBuilder(及其已经被废弃地祖先StringBuffer)。

现在你已经知道了如何构建不可变的类,并且了解了不可变性的优点和缺点,现在我们来讨论其他的一些设计方案。前面提到过,为了确保不可变性,类绝对不允许自生被子类化。除了使类成为final的这种方式之外,还有另一种更加灵活的办法可以做到这一点。不可变的类变成final的另一种办法是,让类的所有构造器都变成私有的或者包级私有的,并添加公有的静态工厂来代替公有的构造器(详见第1条)。为了具体说明这种办法,下面以Complex为例,看看如果使用这种方法:

这种方法虽然并不常用,但它通常是最好的替代方法。它最灵活, 因为它允许使用多个包级私有的实现类。对于处在包外的客户端而言,不可变的类实际上是final的 ,因为不可能对来自另一个包的类、缺少公有的或者受保护的构造器的类进行扩展。除了允许多个实现类的灵活性之外,这种方法还是得有可能通过改善静态工厂的对象缓存能力,在后续的发行版本中改进该类的性能。

当BigIntege和BigDecimal刚被编写出来的时候,对此“不可变的类必须为final”的说法还没有得到广泛的理解,所以它们的所有方法都有可能被覆盖。遗憾的是,为了保持向后兼容,这个问题一直无法得以修正。 如果你正在编写一个类,它的安全性依赖于来自不可信任客户端的BigInteger或者BigDecimal参数的不可变性,就必须进行检查,以确保这个参数是否为"真正的"BigInteger或者BigDecimal,而不是不可信任子类的实例。如果是后者,就必须在假设它可能是可变的前提下对它进行保护性拷贝 (详见第50条):

本条开头关于不可变类的诸多规则指出,没有方法会修改对象,并且它的所有域都必须是final的。实际上,这些规则比真正的要求更强硬了一点,为了提高性能可以有所放松。事实上应该是这样:没有一个方法能够对对象的状态产生外部可见的改变。 然而,许多不可变的类拥有一个或者多个非final的域,它们在第一次被请求执行这些计算的时候,把一些开销昂贵的计算结果缓存在这些域中。如果将来再次请求同样的计算,就直接返回这些缓存的值,从而节约了重新计算所需要的开销。这种技巧可以很好的工作,因为对象是不变的,它的不可变性保证了这些计算如果被再次执行,就会产生同样的结果

例如,PhoneNumber类的hashCode方法(详见第11条)在第一次被调用的时候,计算出散列码,然后把它缓存起来,以备将来再次调用时使用。这种方法是延迟初始化(详见第83条)的一个例子,String类也用到了。

有关序列化功能的一条告诫有必要在这里提出来。如果你选择让自己的不可变类实现Serializable接口,并且它包含一个或者多个指向可变对象的域,就必须提供一个显式的readObject或者readResolve方法,或者使用ObjectOutputStreamwriteUnshared和ObjectOutputStreamreadUnshared方法,即便默认的序列化形式是可以接受的,也是如此。否则,攻击者可能从不可变的类创建可变的实例。

关于这个话题的详情请参考第88条。

总之,坚决不要为每个get方法编写一个相应的set方法。 除非有很好的理由要让类成为可变的类,否则它就应该是不可变的 。不可变的类有许多优点,唯一的缺点是在特定的情况下存在潜在的性能问题。 你应该总是使一些小的值对象,比如PhoneNumber和Complex成为不可变的 。(在Java平台类库中,有几个类如javautilDate和javaawtPoint,它们本应该是不可变得,单实际上却不是。)你也应该认真考虑把一些较大的值对象做成不可变的,例如String和BigInteger。只有当你确认有必要实现令人满意的性能(详见第67条),才应该为不可变的类提供公有的可变配套类。

对于某些类而言,其不可变性是不切实际的。 如果类不能被做成不可变的,仍然应该尽可能地限制它的可变性 。降低对象可以存在的状态数,可以更容易地分析该对象地行为,同时降低出错地可能性。因此,除非有令人信服地理由使域变成非final的,否则让每个域都是final的。结合这条的建议和第15条的建议,你自然倾向于: 除非有令人信服的理由要使域变成非final的,否则要使每个域都是private final 的

构造器应该创建完全初始化的对象,并建立其所有的约束关系 。不要在构造器或者静态工厂之外再提供公有的初始化方法,除非有令人信服的理由必须这么做。同样地,也不应该提供”重新初始化“地方法(它使得对象可以别重用,就好像这个对象是由另一个不同地初始化状态构造出来地一样)。与所增加地复杂性相比,“重新初始化”方法通常并没有带来太多地性能优势。

通过CountDownLatch类地例子可以说明这些原则。它是可变的,但是它的状态空间被有意地设计得非常小。比如创建一个实例,只使用一次,它的任务就完成了:一旦定时器的计数达到零,就不能重用了。

最后值得注意的一点与本条目中的Complex类有关。这个例子只是被用来演示不可变性的,它不是一个工业强度的复数实现。它对复数乘法和除法使用标准的计算公式,会进行不正确的四舍五入,并且对复数NaN和无穷打也没有提供很好的语义。

Byte b=new Byte(String a);

这个构造方法中的字符串a,必须是10十进制数子组成的字符串,以表示 String 参数所指示的 byte 值。该字符串以使用基数 10 的 parseByte 方法所使用的方式被转换成一个 byte 值。

这个构造方法是一个精度问题,和大数的BigInteger a=new BigInteger(String a)

同样的道理,a必须是由数字组成的字符串

voidclose()

关闭此扫描器。 Patterndelimiter()

返回此 Scanner 当前正在用于匹配分隔符的 Pattern。 StringfindInLine(Pattern pattern)

试图在忽略分隔符的情况下查找下一个指定模式。 StringfindInLine(String pattern)

试图在忽略分隔符的情况下查找下一个从指定字符串构造的模式。 StringfindWithinHorizon(Pattern pattern, int horizon)

试图查找下一个指定模式。 StringfindWithinHorizon(String pattern, int horizon)

试图在忽略分隔符的情况下查找下一个从指定字符串构造的模式。 booleanhasNext()

如果此扫描器的输入中有另一个标记,则返回 true。 booleanhasNext(Pattern pattern)

如果下一个完整标记与指定模式匹配,则返回 true。 booleanhasNext(String pattern)

如果下一个标记与从指定字符串构造的模式匹配,则返回 true。 booleanhasNextBigDecimal()

如果通过使用 nextBigDecimal() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 BigDecimal,则返回 true。 booleanhasNextBigInteger()

如果通过使用 nextBigInteger() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 BigInteger 值,则返回 true。 booleanhasNextBigInteger(int radix)

如果通过使用 nextBigInteger() 方法,此扫描器输入信息中的下一个标记可以解释为指定基数中的一个 BigInteger 值,则返回 true。 booleanhasNextBoolean()

如果通过使用一个从字符串 "true|false" 创建的大小写敏感的模式,此扫描器输入信息中的下一个标记可以解释为一个布尔值,则返回 true。 booleanhasNextByte()

如果通过使用 nextByte() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个字节值,则返回 true。 booleanhasNextByte(int radix)

如果通过使用 nextByte() 方法,此扫描器输入信息中的下一个标记可以解释为指定基数中的一个字节值,则返回 true。 booleanhasNextDouble()

如果通过使用 nextDouble() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 double 值,则返回 true。 booleanhasNextFloat()

如果通过使用 nextFloat() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 float 值,则返回 true。 booleanhasNextInt()

如果通过使用 nextInt() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 int 值,则返回 true。 booleanhasNextInt(int radix)

如果通过使用 nextInt() 方法,此扫描器输入信息中的下一个标记可以解释为指定基数中的一个 int 值,则返回 true。 booleanhasNextLine()

如果在此扫描器的输入中存在另一行,则返回 true。 booleanhasNextLong()

如果通过使用 nextLong() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 long 值,则返回 true。 booleanhasNextLong(int radix)

如果通过使用 nextLong() 方法,此扫描器输入信息中的下一个标记可以解释为指定基数中的一个 long 值,则返回 true。 booleanhasNextShort()

如果通过使用 nextShort() 方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 short 值,则返回 true。 booleanhasNextShort(int radix)

如果通过使用 nextShort() 方法,此扫描器输入信息中的下一个标记可以解释为指定基数中的一个 short 值,则返回 true。 IOExceptionioException()

返回此 Scanner 的底层 Readable 最后抛出的 IOException。 Localelocale()

返回此扫描器的语言环境。 MatchResultmatch()

返回此扫描器所执行的最后扫描 *** 作的匹配结果。 Stringnext()

查找并返回来自此扫描器的下一个完整标记。 Stringnext(Pattern pattern)

如果下一个标记与指定模式匹配,则返回下一个标记。 Stringnext(String pattern)

如果下一个标记与从指定字符串构造的模式匹配,则返回下一个标记。 BigDecimalnextBigDecimal()

将输入信息的下一个标记扫描为一个 BigDecimal。 BigIntegernextBigInteger()

将输入信息的下一个标记扫描为一个 BigInteger。 BigIntegernextBigInteger(int radix)

将输入信息的下一个标记扫描为一个 BigInteger。 booleannextBoolean()

扫描解释为一个布尔值的输入标记并返回该值。 bytenextByte()

将输入信息的下一个标记扫描为一个 byte。 bytenextByte(int radix)

将输入信息的下一个标记扫描为一个 byte。 doublenextDouble()

将输入信息的下一个标记扫描为一个 double。 floatnextFloat()

将输入信息的下一个标记扫描为一个 float。 intnextInt()

将输入信息的下一个标记扫描为一个 int。 intnextInt(int radix)

将输入信息的下一个标记扫描为一个 int。 StringnextLine()

此扫描器执行当前行,并返回跳过的输入信息。 longnextLong()

将输入信息的下一个标记扫描为一个 long。 longnextLong(int radix)

将输入信息的下一个标记扫描为一个 long。 shortnextShort()

将输入信息的下一个标记扫描为一个 short。 shortnextShort(int radix)

将输入信息的下一个标记扫描为一个 short。 intradix()

返回此扫描器的默认基数。 voidremove()

Iterator 的这种实现不支持移除 *** 作。 Scannerreset()

重置此扫描器。 Scannerskip(Pattern pattern)

在忽略分隔符的情况下跳过与指定模式匹配的输入信息。 Scannerskip(String pattern)

跳过与从指定字符串构造的模式匹配的输入信息。 StringtoString()

返回此 Scanner 的字符串表示形式。 ScanneruseDelimiter(Pattern pattern)

将此扫描器的分隔模式设置为指定模式。 ScanneruseDelimiter(String pattern)

将此扫描器的分隔模式设置为从指定 String 构造的模式。 ScanneruseLocale(Locale locale)

将此扫描器的语言环境设置为指定的语言环境。 ScanneruseRadix(int radix)

将此扫描器的默认基数设置为指定基数。

拷贝构造函数,是一种特殊的构造函数,它由编译器调用 来完成一些基于同一类的其他对象的构建及初始化。其唯一的参数(对象的引用)是不可变的(const类型)。此函数经常用在函数调用是用户定义了性的值传递以及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。

楼主你的数字太大换了好几个类型才解决了

先说答案。。。20个fab数列分子分母和

9552484077401/309601753890

30854101946705867

主函数

import javamathBigInteger;

public class Run {

private BigInteger one=new BigInteger("1");

private BigInteger two=new BigInteger("2");

private BigInteger fab(BigInteger m){

if(mtoString()equals("1")) return one;

if(mtoString()equals("2")) return one;

return fab(msubtract(one))add(fab(msubtract(two)));

}

public static void main(String[] args){

Run run=new Run();

NumberAdd add=new NumberAdd();

int sumBegin=3;

Fraction last=null;

for(int i=sumBegin;i<sumBegin+20;i++){

BigInteger sumTemp=runfab(new BigInteger(IntegertoString(i)));

BigInteger demoTemp=runfab(new BigInteger(IntegertoString(i-1)));

Fraction result=new Fraction();

resultsetDenominator(demoTemp);

resultsetNumerator(sumTemp);

if(last==null){

last=result;continue;

}else{

last=addgetFractionSum(last, result);

}

}

Systemoutprintln(lastgetFraction());

Systemoutprintln(lastgetNumerator()doubleValue()/lastgetDenominator()doubleValue());

}

}

分数相加

import javamathBigInteger;

public class NumberAdd {

public Fraction getFractionSum(Fraction sumadd,Fraction summand){

Fraction result=new Fraction();

resultsetNumerator(sumaddgetNumerator()multiply(summandgetDenominator())add(summandgetNumerator()multiply(sumaddgetDenominator())));

resultsetDenominator(sumaddgetDenominator()multiply(summandgetDenominator()));

reduction(result);

return result;

}

private void reduction(Fraction content){

//最大公约

BigInteger m=contentgetNumerator();BigInteger n=contentgetDenominator();

BigInteger number=mgcd(n);

//最大公约数为1时不约分

if(!numbertoString()equals("1")){

contentsetDenominator(contentgetDenominator()divide(n));

contentsetNumerator(contentgetNumerator()divide(n));

}

}

}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/13495505.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-09-01
下一篇2025-09-01

发表评论

登录后才能评论

评论列表(0条)

    保存