简体   繁体   English

我会导致浮点精度错误吗?

[英]Can I cause a floating point precision error?

I have a simple (perhaps naive) question - I'm trying to test a scenario, and was wondering if it's possible to cause a floating point precision error when parsing a string to number (is there a magic number that will cause a FPPE?).我有一个简单的(也许是幼稚的)问题 - 我正在尝试测试一个场景,并且想知道在将字符串解析为数字时是否可能导致浮点精度错误(是否有会导致 FPPE 的幻数? )。

eg例如

parseFloat("4.015") // = 4.0149999999999994
const foo = 4.015 // = 4.0149999999999994

Or, is it only possible to produce a floating point precision error as a result of an operation?或者,是否只能由于操作而产生浮点精度错误?

 console.log(4.015) console.log(parseFloat("4.015")) console.log(4.015 * 100)

Converting a number from a decimal in a string to binary floating-point is an operation, and it does produce “precision errors.”将字符串中的十进制数转换为二进制浮点数是一种操作,它确实会产生“精度错误”。 If the source number is not representable in the destination format, it is rounded.如果源编号在目标格式中无法表示,则将其四舍五入。

In the examples you show, every operation has a rounding error, except for converting the source text 100 to the number 100.在您展示的示例中,每个操作都有一个舍入误差,除了将源文本100转换为数字 100。

In console.log(4.015) , the decimal numeral “4.015” represents the number 4.015.console.log(4.015) ,十进制数字“4.015”代表数字 4.015。 When this is converted to the IEEE-754 64-bit binary floating-point that JavaScript uses, the result is 4.01499999999999968025576890795491635799407958984375.将其转换为 JavaScript 使用的 IEEE-754 64 位二进制浮点数时,结果为 4.0149999999999968025576890799407958984375。 (That has lots of digits, but it is actually represented internally in a form equivalent to 4520488125973135 times 2 −50 .) Then, to print this to the console, it is converted from binary floating-point to decimal. (它有很多数字,但它实际上在内部以相当于 4520488125973135 乘以 2 -50的形式表示。)然后,为了将其打印到控制台,将其从二进制浮点数转换为十进制数。 When doing the conversion, JavaScript uses just enough decimal digits to uniquely distinguish the value from neighboring values that are representable in binary floating-point.在进行转换时,JavaScript 使用刚好足够的十进制数字来唯一地区分该值与可表示为二进制浮点数的相邻值。 The result is the string “4.015”.结果是字符串“4.015”。 So the binary floating-point value has been rounded to a different decimal value—producing the same string as the original.因此,二进制浮点值已四舍五入为不同的十进制值——生成与原始字符串相同的字符串。 So, in console.log(4.015) , there are actually two conversion operations, there is rounding error in both of them, and the behavior of the software acts to conceal the rounding errors.因此,在console.log(4.015) ,实际上有两个转换操作,它们都存在舍入错误,并且软件的行为会隐藏舍入错误。

In console.log(parseFloat("4.015")) , the same thing happens, except the first conversion is done when parseFloat is called instead of when 4.015 is interpreted in the source code.console.log(parseFloat("4.015")) ,发生了同样的事情,除了第一次转换是在调用parseFloat时完成的,而不是在源代码中解释4.0154.015

In console.log(4.015 * 100) , there are four operations and three rounding errors:console.log(4.015 * 100) ,有四个操作和三个舍入错误:

  • 4.015 is converted to binary floating-point, which has the rounding error described above. 4.015被转换为二进制浮点数,它具有上述舍入误差。
  • 100 is converted to binary floating-point, and there is no rounding error because 100 is representable in binary floating-point. 100转换为二进制浮点数,并且没有舍入错误,因为 100 可以用二进制浮点数表示。
  • The two binary floating-point numbers are multiplied, and there is a rounding error, producing 401.49999999999994315658113919198513031005859375.两个二进制浮点数相乘,有舍入误差,产生401.49999999999994315658113919198513031005859375。
  • That result is converted to a decimal string.该结果将转换为十进制字符串。 The result is “401.49999999999994” because we need that many digits to distinguish it from the two neighboring representable values, 401.4999999999998863131622783839702606201171875 and 401.5.结果是“401.49999999999994”,因为我们需要这么多数字来将它与两个相邻的可表示值 401.4999999999998863131622783839702606201171875 和 401.5 区分开来。

In summary:总之:

  • Every operation, including conversions between binary and decimal, may be subject to rounding error.每个操作,包括二进制和十进制之间的转换,都可能存在舍入误差。
  • The default JavaScript formatting acts to conceal some rounding errors;默认的 JavaScript 格式用于隐藏一些舍入错误; round trips from decimal numerals shorter than 16 digits will always produce the original number (within the finite range of the format).从小于 16 位的十进制数字往返将始终产生原始数字(在格式的有限范围内)。

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

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