为什么浮点数据类型的精度不与其大小成正比增长?例如:
std::cout << sizeof(float) << "\n"; // this gives 4 on my machine "debian 64 bit" with "gcc 6.3.0"
std::cout << std::numeric_limits<float>::digits10 << "\n"; // gives 6
std::cout << sizeof(double) << "\n"; // gives 8
std::cout << std::numeric_limits<double>::digits10 << "\n"; // gives 15
std::cout << sizeof(long double) << "\n"; // gives 16
std::cout << std::numeric_limits<long double>::digits10 << "\n"; // gives 18
正如您所看到的,Double
的精度大约是浮动
精度的两倍,这是有意义的,因为Double
的大小是的两倍。浮点
。
但这与双精度和长双精度的情况不同,长双精度的大小是128位,是64位双精度的两倍,但其精度只多出三位!!
我不知道浮点数是如何实现的,但从理性的角度来看,仅为三位精度使用64位内存是否有意义?!
我四处搜索,但没有找到一个简单明了的答案。如果有人能解释为什么长双精度只比双精度高三位数,你能解释一下为什么这与双精度和浮点精度不同吗?
我还想知道如何在不定义自己的数据类型的情况下获得更好的精度,这显然会以性能为代价?
你的问题中有许多错误的假设
首先,C中没有关于类型大小的要求。该标准仅要求每种类型的最小精度,并且。。。
... double类型提供的精度至少与float相同,long double类型提供的精度至少与double相同。float类型的值集是double类型的值集的子集;double类型的值集是长double类型的值集的子集。浮点类型的值表示由实现定义。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
大多数现代实现将浮点和双精度映射到IEEE-754单精度和双精度格式,因为对它们的硬件支持是主流。然而,长双精度并没有得到如此广泛的支持,因为很少有人需要比双精度更高的精度,而这些精度的硬件成本要高得多。因此,一些平台将其映射到IEEE-754双精度,即与双精度相同。如果底层硬件支持,其他一些人将其映射到80位IEEE 754扩展精度格式。否则,长双精度将由算术或IEEE-754四倍精度表示
此外,精度也不会与类型中的位数成线性比例。很容易看出,尽管只有两倍的存储空间,但双精度是浮点精度的两倍多,范围比浮点宽8倍,因为它的有效位为53位,而浮点中为24位,指数位为3位。类型也可以具有陷阱表示或填充位,因此不同的类型可能具有不同的范围,即使它们具有相同的大小并且属于同一类别(整数或浮点)
所以这里重要的是std::numeric\u极限
-malign-双
和-mno-alie-Double
用于控制long Double
-m96bit-long-双
和-m128bit-long-双
用于更改填充大小-mlong-dule-64
,-mlong-dule-80
和-mlong-dule-128
用于控制底层long Double
实现通过更改选项,您将获得以下长双精度的结果
-mlong-double-128:size=16,digits10=33,digits2=113
-m96位长双精度:大小=12,数字10=18,数字2=64
-mlong-double-64:size=8,digits10=15,digits2=53
如果禁用填充,则大小将为10,但由于未对齐,这将以性能为代价。查看编译器资源管理器上的更多演示
在PowerPC中,更改浮点格式时也可以看到相同的现象。使用
-mabi=ibmlongdouble(双-双算术,这是默认值),您将得到(size,digits10,digits2)=(16,31,106),但使用
-mabi=ieeelongdouble,元组将变为(16,33,113)
有关更多信息,您应该阅读https://en.wikipedia.org/wiki/Long_double
我还想知道如何在不定义自己的数据类型的情况下获得更好的精度
要搜索的关键字是任意精度的算术。在任意精度算术软件列表中可以找到各种库。您可以在标记bigint、biginger或任意精度中找到更多信息
除了浮点类型必须满足的一些最低级别外,C标准没有对浮点类型设定固定的要求。
很可能您使用的C实现针对的是英特尔处理器。除了常见的IEEE-754基本32位和64位二进制浮点格式外,Intel还有80位格式。您的C实现可能将其用于长double。
英特尔80位格式的有效位比64位双精度格式多11位。(实际上它使用64,其中双精度格式使用52,但其中一个保留为显式前导1。)11位以上意味着211=2048倍的有效位值,这大约是三位以上的十进制数字。
80位格式(即10个字节)优先与16个字节的倍数对齐,因此包括6个字节的填充,以使长双字节大小为16个字节的倍数。
“精度”并不是浮点值的全部。这也是关于“幅度”(但不确定该术语是否正确!):表示的值可以变大(或变小)?
为此,请尝试打印每种类型的max_exponent
:
std::cout << "float: " << sizeof(float) << "\n";
std::cout << std::numeric_limits<float>::digits << "\n";
std::cout << std::numeric_limits<float>::max_exponent << "\n";
std::cout << "double: " << sizeof(double) << "\n";
std::cout << std::numeric_limits<double>::digits << "\n";
std::cout << std::numeric_limits<double>::max_exponent << "\n";
std::cout << "long double: " << sizeof(long double) << "\n";
std::cout << std::numeric_limits<long double>::digits << "\n";
std::cout << std::numeric_limits<long double>::max_exponent << "\n";
ideone上的输出:
float: 4
24
128
double: 8
53
1024
long double: 16
64
16384
因此,额外的位并不都用于表示更多的数字(精度),而是允许指数更大。使用IEE 754long Double
中的措辞主要增加了指数范围而不是精度。
我上面的ideone示例显示的格式显示(可能)“x86扩展精度格式”,它为整数部分分配1位,为小数部分分配63位(总共64位),为指数分配15位(2^(15-1) = 16384, 1位用于指数的符号)。
注意,C标准只要求长双精度至少与双精度相同,因此长双精度可以是所示x86扩展精度格式(最有可能)的同义词,也可以是更好的格式(仅限PowerPC上的AFAIK GCC)。
我还想知道如何在不定义自己的数据类型的情况下获得更好的精度,这显然会以性能为代价?
您需要自己编写(当然是一种学习体验,最好不要为生产代码编写)或使用库,如GNU MPFR或Boost。多精度。
本文向大家介绍PHP浮点数据类型,包括了PHP浮点数据类型的使用技巧和注意事项,需要的朋友参考一下 定义和用法 在PHP中,float数据类型表示任何数字,并带有小数部分。小数部分可以包含小数点后的数字,或者可以使用e或E以科学计数法表示。例如,科学计数法中的100是10e2。 浮点数的大小取决于硬件/ OS平台,尽管通常会精确到小数点后14位。 语法 为了更好的可读性,整数文字可以使用“ _”
在处理浮点数时,我对C#中“精度”的实际含义有些怀疑。如果逻辑性不强,而且解释太长,我提前道歉。 我知道浮点数(例如)的精度为6到9位。假设我们有下一个代码: 我在控制台里得到了确切的数字。现在,让我们使用下一个代码: 打印了一个不同的数字:,即使这个数字有9位数,这也是极限。 这是我的第一个怀疑。精度取决于数字本身还是计算机的结构? 此外,数据以位的形式存储在计算机中,在中间,我记得将数字的小数
我试图控制我在字符串中添加的位数,但我无法控制它,因为我正在打印字符串数组。 但是我最终得到了一个字符串数组,如下所示: 0.050000//3.000000//... 在将浮点数添加到字符串之前,有什么方法可以控制浮点数的精度吗? (所以我可以有一个结果字符串控制一个固定数量的数字) 0.05//3.00// ...
问题内容: $a = ‘35’; $b = ‘-34.99’; echo ($a + $b); 结果为0.009999999999998 这是怎么回事?我想知道为什么我的程序不断报告奇怪的结果。 为什么PHP不返回预期的0.01? 问题答案: 因为浮点运算!=实数运算。对于一些浮子和,由不精确性引起的差异的说明是。这适用于使用浮点数的任何语言。 由于浮点数是具有有限精度的二进制数,因此存在有限数量
本文向大家介绍Fortran 浮点数精度,包括了Fortran 浮点数精度的使用技巧和注意事项,需要的朋友参考一下 示例 类型的浮点数real不能有任何实数值。它们可以表示实数,最多可以包含一定数量的十进制数字。 FORTRAN 77保证了两种浮点类型,而最新的标准则至少保证了两种实数类型。实变量可以声明为 x这是默认类型的实数,并且y是比更大的十进制精度的实数x。在Fortran 2008中,十
本文向大家介绍C ++中浮点数的精度(floor(),ceil(),trunc(),round()和setprecision()),包括了C ++中浮点数的精度(floor(),ceil(),trunc(),round()和setprecision())的使用技巧和注意事项,需要的朋友参考一下 浮点数的精度是浮点数可以保留小数点后的值的精度。 例如10/6 = 1.6666666…这些具有重复的小