简体   繁体   English

打印浮点数的精确值

[英]Printing exact values for floats

How does a program (MySQL is an example) store a float like 0.9 and then return it to me as 0.9? 程序(以MySQL为例)如何存储像0.9这样的浮点数,然后以0.9的形式返回给我? Why does it not return 0.899...? 为什么不返回0.899 ...?

The issue I am currently experiencing is retrieving floating point values from MySQL with C++ and then reprinting those values. 我目前遇到的问题是使用C ++从MySQL检索浮点值,然后重新打印这些值。

What's happening, in a nutshell, is that the function which converts the floating-point approximation of 0.9 to decimal text is actually coming up with a value like 0.90000....0123 or 0.89999....9573 . 简而言之,发生的事情是将0.9的浮点近似值转换为十进制文本的函数实际上是一个像0.90000....01230.89999....9573 This gets rounded to 0.90000...0 . 取整到0.90000...0 And then these trailing zeros are trimmed off so you get a tidy looking 0.9 . 然后修剪掉这些尾随的零,以便获得0.9的整洁效果。

Although floating-point numbers are inexact, and often do not use base 10 internally, they can in fact precisely save and recover a decimal representation. 尽管浮点数不精确,并且通常在内部不使用基数10,但实际上它们可以精确地保存和恢复十进制表示形式。 For instance, an IEEE 754 64 bit representation has enough precision to preserve 15 decimal digits. 例如,IEEE 754 64位表示具有足够的精度来保留15个十进制数字。 This is often mapped to the C language type double , and that language has the constant DBL_DIG , which will be 15 when double is this IEEE type. 这通常映射到C语言类型double ,并且该语言具有常量DBL_DIG ,当此IEEE类型double时将为15。

If a decimal number with 15 digits or less is converted to double, it can be coverted back to exactly that number. 如果将15位或更少的十进制数字转换为双精度数字,则可以将其隐蔽地精确返回该数字。 The conversion routine just has to round it off at 15 digits; 转换例程只需将其四舍五入为15位数字; of course if the conversion routine uses, say, 40 digits, there will be messy trailing digits representing the error between the floating-point value and the original number. 当然,如果转换例程使用40位数字,则会出现乱码尾随数字,表示浮点值和原始数字之间的错误。 The more digits you print, the more accurately rendered is that error. 您打印的位数越多,该错误的呈现越准确。

There is also the opposite problem: given a floating-point object, can it be printed into decimal such that the resulting decimal can be scanned back to reproduce that object? 还有一个相反的问题:给定一个浮点对象,可以将它打印成十进制,以便可以将生成的十进制扫描回去以重现该对象吗? For an IEEE 64 bit double, the number of decimal digits required for that is 17. 对于IEEE 64位double,其所需的十进制数字为17。

There are software libraries, like Gnu MP that implement arbitrary precision arithmetic, that calculate floating point numbers to specified precision. 有一些软件库,例如Gnu MP ,可以实现任意精度算术,可以将浮点数计算为指定的精度。 Using Gnu MP you can, for example, add 0.3 to 0.6, and get exactly 0.9. 例如,使用Gnu MP,您可以将0.3加到0.6,并精确地得到0.9。 No more, no less. 不多不少。

Database servers do pretty much the same thing. 数据库服务器做几乎相同的事情。

For normal, run of the mill applications, native floating point arithmetic is fast, and it's good enough. 对于正常运行的工厂应用程序,本机浮点运算速度很快,并且足够好。 But database servers typically have plenty of spare CPU cycles. 但是数据库服务器通常有大量的备用CPU周期。 Their limiting factors will not be available CPU, but things like available I/O bandwidth. 它们的限制因素不是可用的CPU,而是可用的I / O带宽。 They'll have plenty of CPU cycles to burn on executing complicated arbitrary precision arithmetic calculations. 在执行复杂的任意精度算术计算时,它们将消耗大量CPU周期。

There are a number of algorithms for rounding floating point numbers in a way that will result in the same internal representation when read back in. For an overview of the subject, with links to papers with full details of the algorithms, see 有许多算法可以使浮点数四舍五入,以便在读回时产生相同的内部表示形式。有关该主题的概述,以及包含论文的链接以及该算法的完整详细信息,请参见

Printing Floating-Point Numbers 打印浮点数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM