java.lang.OutOfMemoryError及解决方案

   有同事在工作中遇到了一个奇怪的问题,这个问题与浮点数计算相关,代码如下:

  1 #include

  2 using namespace std;

  3

  4 int main()

  5 {

  6 double s = 6.0;

  7 double e = 0.2;

  8

  9 cout << static_cast(s/e) << endl;

  10 return 0;

  11 }

  这段代码看起来很简单,心算一下,应该输出30才对。

  但结果却是我们在32 和 64位 linux平台下得到了不同的结果,分别是29和30,意想不到对吧?

  然后,如果把代码改成如下:

  1 #include

  2 using namespace std;

  3

  4 int main()

  5 {

  6 double s = 6.0;

  7 double e = 0.2;

  8

  9 double d = s/e;

  10

  11 cout << static_cast(d) << endl;

  12 return 0;

  13 }

  你会发现在两个平台上都得到了相同的“正确”结果!为什么呢?

  稀疏的浮点数

  众所周知,计算机是无法精确地表示所有浮点数的,无理数的稠密性使得无论我们用多高精度的数据类型来表示浮点数,所能表示的范围相对整个无理数来说都是相当相当地稀疏疏。

  因此在计算机的世界里,我们只能尽可能用有限精度地来表示一定范围的数据,至于那些没法精确表示的数字,就只能在计算机所能表示的范围里找一个和它最接近的数来凑和凑和。

  这个好像比较好理解,比如说根号2什么的,我们都知道这些无理数不能在计算机里完全精确的表示,但还有那么一些有理数,在10进制里虽然可以精确地表示,在2进制里却也是无法精确表示的,比如说上面例子中的0.2,你如果对此有怀疑,可以好好回顾一下怎么把小数转成二进制,然后慢慢用笔在纸上演算一下。

  讲这些,无非还是想说明,计算机世界里的浮点数是相当疏松地,借用《深入理解操作系统》一书里的一张图,让大家

  浮点数的折断与转换

  因为很多小数是无法精确表示的,因此我们只能尽可能在有限精度的小数里找到最近接近的数来近似那些无限的小数。

  那么计算机是怎么样来做这些逼近的呢?常用的有如下4种方式:

  其中第一种是默认使用方式,需要注意的是这些折断方式并不仅限于由浮点数转为整数,浮点数之间也是适用的。

  在C语言中,浮点数与整数的转换有以下几条原则:

  1) int型转为float,不会overfloat,但有些数用float无法表示,因此可能需要rounding,记住float很稀疏。

  2) 由int或float转为double时,精度不会丢失,毕竟double精度高太多了。

  3) double转为float时,很可能会overfloat, 转换则用round-to-even的方式(默认)进行。

  4) 由float, double转换为int时用round-to-zero的方式转换,当然也很可能会被截断。

  请注意第3条,第4条原则,它们转换时使用的不同原则有时会导致一些很微妙的结果。

  Intel IA32 浮点运算

  IA32处理器和很多其它一些处理器一样,有专门用于保存浮点数的寄存器,当在cpu中进行浮点数运算时,这些寄存器就用来保存输入输出及相关的中间结果。

  但IA32有一个比较特别的地方,它的浮点数寄存器是80位的,而我们在程序中只用到32和64位两种类型,因此当把float,double放入到cpu中时,它们都会被转换成了80位,然后以80位的方式进行运算,最后得到的结果再转换回来。这样特性使得浮点数的计算可以相对更精确些,但同时,一不小心很可能也会引出一些意想不到的问题。

  你可能突然恍然大悟了,对的,我们最开始提到那个奇怪的问题就与此相关。

  s/e得到结果是个80位的浮点数,由这个浮点数先转换成double再转成int,与直接就转换成int,结果很可能是不同的。

  比如在我们的例子中,s/e ~ 29.999999....时,s/e转换成double使用round-to-even的方式,会得到也许是30.0000001,再转成整形时,得到30.

  但如果直接由29.99999...转换成整型,得到却是29。

时间: 2024-09-20 04:49:48

java.lang.OutOfMemoryError及解决方案的相关文章

java.lang.OutOfMemoryError: Java heap space java内存溢出问题 有错误信息

问题描述 java.lang.OutOfMemoryError: Java heap space java内存溢出问题 有错误信息 2013-12-26 11:18:09 [ERROR]-[rmss:165] Housekeeping log.error( : java.lang.OutOfMemoryError: Java heap spaceat java.lang.AbstractStringBuilder.(AbstractStringBuilder.java:45)at java.la

springmvc 实现文件下载 出现异常java.lang.OutOfMemoryError: Java heap space

问题描述 springmvc 实现文件下载 出现异常java.lang.OutOfMemoryError: Java heap space 网上找解决方案,一般都是tomcat中添加-Xms256m -Xms512m等配置,但是不行啊. 我的是MyEclipse里的tomcat. 下载20M(包括)以内的文件没问题,超过就会报异常,有什么解决办法吗? 还有是不是请求下载文件时,服务器会把文件全部装入内存再发过来,还是分成多个部分发送,超过内存大小的文件如何发送呢? ** --异常信息 ** ty

byte-java 上传大文件(1G)报错 java.lang.OutOfMemoryError

问题描述 java 上传大文件(1G)报错 java.lang.OutOfMemoryError java.lang.OutOfMemoryError: Java heap space java.util.Arrays.copyOf(Arrays.java:2271) java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113) java.io.ByteArrayOutputStream.ensureCapacity(Byt

找出导致java.lang.OutOfMemoryError: Java heap space问题的数据

问题描述 引起java.lang.OutOfMemoryError:Javaheapspace异常,可能是由JAVA的堆栈设置太小的原因,在网上查了下都是调整jvm大小的,但这个方法治标不治本呀!!!!,当数据增大是依然会报溢出错误,总不至于再把jvm调大吧.有没有办法找到导致溢出的数据,之前听同事说有办法找到,但是不知道怎么找的,求大神指导 解决方案 解决方案二:upup解决方案三:错误是在tomcat启动的时候报的解决方案四:是不是你程序代码的问题呢?解决方案五:引用3楼rui888的回复:

当tomcat报:java.lang.OutOfMemoryError: Java heap space

问题描述 我要导出一个10W条记录的文件,但是tomcat后台报java.lang.OutOfMemoryError:Javaheapspace异常我用已经用了两种方法不行1./tomcat/bin/catalina.bat加上下面的命令:在remGuessCATALINA_HOMEifnotdefined这句话的下面加setJAVA_OPTS=-Xms32m-Xmx256m2.修改TOMCAT_HOME/bin/catalina.sh在「echo"UsingCATALINA_BASE:$CAT

java.lang.OutOfMemoryError: CG(q0) 内存溢出问题

问题描述 java.lang.OutOfMemoryError: CG(q0) [javelin/java/JavaScope._resolve([Ljavelin/java/ast/NameNode;II)Ljava/lang/Object;] JVM@cgFail (src/jvm/code/codemanagerat javelin.java.JavaScope.resolve(JavaScope.java:1454)at javelin.java.JavaScope.resolveTyp

SSH出现Caused by: java.lang.OutOfMemoryError: Java

问题描述 [Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name '/addUser' defined in class path resource [applicationContext.xml]: Cannot resolve reference to bean 'userDAOProxy' while set

java.lang.OutOfMemoryError: unable to create new native thread这个异常怎么解决?

问题描述 2011-3-1516:39:49org.apache.catalina.core.StandardWrapperValveinvoke严重:Servlet.service()forservletactionthrewexceptionjava.lang.OutOfMemoryError:unabletocreatenewnativethreadatjava.lang.Thread.start0(NativeMethod)atjava.lang.Thread.start(Unknown

java.lang.OutOfMemoryError错误的问题,怎么办啊,打包完了手机顽童可以打开

问题描述 importjava.io.IOException;importjava.io.InputStream;importjava.util.Random;importjava.io.ByteArrayInputStream;importjava.io.IOException;importjavax.microedition.media.Manager;importjavax.microedition.media.MediaException;各位仁兄,小弟初学,不知道代码哪里的原因,帮帮忙