简单的浮点乘法没有给出预期的结果

时间:2019-09-06 05:31:45

标签: c

当给定输入var exports = module.exports = {}; const lineReader = require('line-reader'); const Obj = require("./Data") const Data = Obj.Data; Promise = require('bluebird'); var eachLine = Promise.promisify(lineReader.eachLine); var records = []; exports.readAllLines = async function() { await eachLine('./datafile.dat', function (line) { parseLine(line); }); return records; } function parseLine(inputLine) { var splitArray = inputLine.split("\t"); var date = new Date(Date.parse(splitArray[0])); var o= splitArray[1]; var h= splitArray[2]; var l= splitArray[3]; var c= splitArray[4]; var v= splitArray[5]; var dataObject = new Data (date, o, h, l, c, v); records.push(dataObject); } 时,我希望输出是数学上正确的答案150,但是我得到了错误的输出70685.7750

70685.7812

3 个答案:

答案 0 :(得分:4)

floatdouble的数字在内存中的显示不十分准确。主要原因是内存有限,而大多数非整数不是。

最好的例子是PI。您可以根据需要指定任意多个数字,但仍然是一个近似值。

表示数字的精度有限是以下规则的原因:

  

在处理floatsdouble数字时,不要检查是否相等(m == n),而是要检查它们之间的差异是否小于某个错误({{1} })


也请注意,如评论中所述,上述规则也不是“所有规则的母体规则”。还有其他规则。

必须对每种特定情况进行仔细的分析,以使应用程序正常工作。

(感谢@EricPostpischil的提醒)

答案 1 :(得分:2)

float类型的变量通常是IEEE-754 32位浮点数。

数字3.14159无法完全存储在IEEE-754 32位浮点数中-最接近的值大约为3.14159012150 * 150 * 3.1415901270685.7777,可以在32位浮点数中表示的与此 this 最接近的值是70685.78125,然后使用{{ 1}},您将看到%.4f

对此的另一种思考方式是,您的70685.7812值最终只能精确到第六个有效数字,因此-当您仅计算一系列乘法时-您的结果也仅精确到第六个有效数字(即n)。 (在一般情况下,情况可能会更糟-例如,将两个接近值相减会导致相对误差大幅增加。)

如果您切换为使用70685.8类型的变量(并将double更改为使用scanf()),那么您很可能会得到想要的答案。 %lf通常是64位浮点数,这意味着double值的表示形式中的错误以及结果很小,不会影响小数点后第四位。

答案 2 :(得分:0)

您是否听说过floatdouble的值并不总是那么准确,精确度有限?您是否听说过float类型给您带来相当于大约7个十进制数字的精度?这就是这个意思。您的预期答案和实际答案分别为70685.7 7 50和70685.7 8 12,而第七位数字与预期的差不多。

  

我希望输出结果是数学上正确的答案

很抱歉让您失望,但这是您的错误。通常,当您执行浮点运算时,您从不不会得到数学上正确的答案,始终会得到数学上正确答案的有限精度近似值。

此类问题的规范SO答案在Is floating point math broken?处收集。您可能需要阅读其中的一些答案,以获得更多启示。

相关问题