如何使用 JavaScript 在 QtQuick Qml 中进行大量数学运算

use*_*395 5 javascript math bash qt qml

我想计算太阳围绕银河系的情况;the Math Formula is ((241828072282107.5071453596951 * 666) * 2) * 3.14159265359, using QML JavaScript I get the answer 1011954093357316100, when the correct answer is 1011954093357316200, a 100 miles off.

galaxyRadius="241828072282107.5071453596951";

currentTrackNumber=666; // Track Number like on a Record

pIe="3.14159265359"; // not the same as Math.PI
Run Code Online (Sandbox Code Playgroud)

我必须使用字符串,因为将这些大小的数字转换为浮点数会截断精度,我正在转换旧的 bash 脚本,并且它与 bc 一起工作得很好,而不是数学。

我已经尝试过这个:

orbitDist = ((( Number.parseFloat(galaxyRadius).toPrecision(20) * currentTrackNumber) * 2) * Number.parseFloat(pIe).toPrecision(12) );
Run Code Online (Sandbox Code Playgroud)

我得到的结果与以下相同:

orbitDist = ((( galaxyRadius * currentTrackNumber) * 2) * pIe );
Run Code Online (Sandbox Code Playgroud)

来自bash:

echo "$(bc <<< "scale=13;((241828072282107.5071453596951 * 666) * 2) * 3.14159265359")"
Run Code Online (Sandbox Code Playgroud)

Bash 是对的,而 JavaScript 错了近 100 英里,这太疯狂了,这让我吓坏了,JavaScript 浮点数学怎么会相差这么远,这只是一个例子,我有一整个应用程序充满了数字很近,但还不够近,相差 100 英里是不可接受的。

我不想处理指数,我想要作为整数的值,字符串很好,它作为字符串存储在数据库中,我只需要数学是正确的。

这是一个 QtQuick、QML、Felgo 应用程序,使用 Qml 和 JavaScript,因此需要在不同的平台上运行。我的下一个想法是 C++,或者适用于此类项目的数学库,JavaScript 或 C++ 的 QML 包装库会很棒,弄清楚如何使 JavaScript 在浮点上不那么糟糕会更好,我发现了一些 JavaScript Web 库,如果没有 Qml 下的大量工作,它们就无法工作,所以我只对有效的内容感兴趣,我做了很多研究,但没有找到我想要的东西。

bir*_*ird 0

因为 JavaScript 目前只支持整数(BigInt)的 bignum 。然后我在计算之前将其转换为 BigInt。并跟踪小数部分重新转换为浮点数。

const galaxyRadius="241828072282107.5071453596951";

const currentTrackNumber=666; // Track Number like on a Record

const pIe="3.14159265359"; // not the same as Math.PI

const orbitDist = ((( galaxyRadius * currentTrackNumber) * 2) * pIe );
console.log(orbitDist)

//// My approad

//Put all number into an array
var arrToMul = [galaxyRadius,currentTrackNumber, 2, pIe]

// Function multiple all item in array with BigInt format
function mulBigInt(arr) {
  return arr.reduce(function (acc, e) {
    return BigInt(e) * acc;
  }, BigInt(1));
}; 

// Function get length of decimal part
function decLength(str) {
  var dec = str.toString().split('.')[1];
  return dec ? dec.length : 0;
}; 

// Function remove point in string to convert float to int
function rmPoint(strNum) {
  return strNum.toString().replace('.', "");
}; 

// Main function
function cal(arr) {
  // Get total decimal part length of all number
  var pointSize = arr.reduce(function (acc, e) {
    return acc + decLength(e);
  }, 0); 
  
  // convert the all item to int (type string)
  var newArr = arr.map(function (e) {
    return rmPoint(e);
  }); 
  // Add point to reconvert BigInt to float(string actually)
  var tmp = mulBigInt(newArr).toString().split('');
  tmp.splice(tmp.length - pointSize, 0, '.'); 
  
  // Return float result with string format
  return tmp.join('');
};
const rs = cal(arrToMul)
console.log(rs, 'converted to BigInt:')
Run Code Online (Sandbox Code Playgroud)