Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 确定一个浮点数是否是另一个浮点数的倍数?_Javascript_Floating Point - Fatal编程技术网

Javascript 确定一个浮点数是否是另一个浮点数的倍数?

Javascript 确定一个浮点数是否是另一个浮点数的倍数?,javascript,floating-point,Javascript,Floating Point,我需要使用JavaScript确定一个浮点数是否是另一个浮点数的倍数 我读过一些关于浮点数的其他问题,我了解到它们不能正确使用模运算符(%)。我也读过,你可以通过乘以10/100/1000等将浮点数转换成整数,但这并不是在所有情况下都能正确工作 例如: var A = 25.13; var B = .0001; var Value = A*1e5; var Step = B*1e5; // Is Value a multiple of Step? if(0 === (Value % Ste

我需要使用JavaScript确定一个浮点数是否是另一个浮点数的倍数

我读过一些关于浮点数的其他问题,我了解到它们不能正确使用模运算符(%)。我也读过,你可以通过乘以10/100/1000等将浮点数转换成整数,但这并不是在所有情况下都能正确工作

例如:

var A = 25.13;
var B = .0001;

var Value = A*1e5;
var Step  = B*1e5;

// Is Value a multiple of Step?
if(0 === (Value % Step)) {
// Do something
}
在这种情况下,该值是步骤的倍数,并且工作正常。但是关于:

var A = 2.2;
var B = .0001;
它应该是一个有效的倍数,但我们得到:

220000.00000000003 % 10 = 2.9103830456733704e-11
小数点后第11位有一个错误的3。我想我可以通过执行以下操作来纠正使用
toFixed()
四舍五入的问题:

var Value = (A*1e5).toFixed(10);
var Step  = (B*1e5).toFixed(10);
但如果你这样做了:

var A = 45436212356482;
var B = .0001;
你会得到:

4543621235648200192.0000000000 % 10.0000000000=2
这是一个有效的倍数,但它认为不是

与:

这不是一个有效的倍数,但它认为是:

4.543621254652216e+21 % 10.0000000000=0
确定一个浮点是否是另一个浮点的倍数有什么巧妙的方法吗?或者这是不可能的

更新:

目标是将用户输入的数字(整数或小数)限制为某些增量

  • 如果增量为1,则用户可以输入1、2、3、4等
  • 如果增量为.5,则用户可以输入.5、1、1.5、2、2.5等
  • 如果增量为.0002,则用户可以输入1,1.001,1.0004,1.0006,但不能输入1.0001

从逻辑角度来看,给定值是或不是给定增量的有效倍数。

因为您处理的是浮点,所以最好确定“关闭”的关闭程度,并使用该值:

function IsMultipleOf(a, b) {
   var result = a % b;
   return (result < 1e-3);
}
函数是多重函数(a,b){
var结果=a%b;
返回(结果<1e-3);
}
我需要使用JavaScript确定一个浮点数是否是另一个浮点数的倍数

如果我们假设浮点数用来近似实数,那么根据定义,每个浮点数都是另一个数的倍数。当然,由于浮点数实际上是有理数的一个子集,所以当然有很多没有公共浮点数除数的浮点数对。例如,尾数中具有不同素数系数的任何两个浮点数都没有公约数。指数的范围进一步限制成对的精确倍数

但也许你不是在寻找具有任意乘法因子的数字,而是那些具有整数除数的数字,并测试结果是否低于所选阈值(通常称为epsilon)

e、 g.函数式伪代码

fmod :: float -> float -> float
fmod a b =
    b - a * floor( b / a )

EPSILON = 1e-5;
divides_to_integer :: float -> float -> boolean
divides_to_integer a b =
    fmod(a, b) < EPSILON
fmod::float->float->float
fmod a b=
b-a*楼层(b/a)
ε=1e-5;
将\u除以\u整数::浮点->浮点->布尔值
将_除以_整数a b=
fmod(a,b)<ε

fmod函数应取自JavaScript数学库。

给出最后两个示例,包括4543621235648200192等,似乎您希望接受整数倍为.0001的数字,而拒绝非的数字,并且您不希望使用.0001,而是使用包含最接近.0001的浮点值的变量

一般来说,这是不可能的。当您将.0001传递给其他对象时,算法无法“知道”它的意图

如果您对问题进行更多限制,可能会有一个解决方案。例如,可以(也许不容易)回答这个问题:浮点值X是最接近.0001整数倍的浮点值吗?(换句话说,是否存在一个整数k,将.0001乘以k并四舍五入到最接近的浮点值,正好得到X?)


所以,为了得到一个解决方案,你需要进一步描述你的目标。您想要步骤的任意值的解决方案,还是只想要某些值的解决方案?由于二进制浮点不能足够精确地表示步长,您有其他方法来描述它吗?例如,它是否总是0.0001的倍数?要接受为倍数的值是否始终是最接近精确数学倍数的二进制浮点数,或者它可能有其他错误?

基本问题是32位浮点数不能正确表示所有实数。例如,如果用户输入0.1,则浮点值将为0.0999994

因此,如果增量为0.1,则无法判断他是否输入了0.1(这将是有效的),或者他是否输入了0.09999。。(这将是无效的)


我的建议是使用整数数据类型,并将其视为固定点数。这样,您就不会失去精度,并且可以轻松检查多重性。

如果我错了,请纠正我,但解决方案如下:

在这种情况下,它可以正常工作。现在假设:

dt = 1.4
>>> dt = 1.3999999999999999
t = 3 * dt
>>> t = 4.1999999999999993
t % dt
>>> 1.3999999999999995
由于舍入误差的作用使得t小于dt的下一个倍数, 模的值更接近dt,而不是0

解决此问题的一种可能方法是检查两种情况:

modt = t % dt
(abs(modt) <= tolerance) or (abs(dt - modt) <= tolerance)
负责这项工作,但这只是猜测。或者

tolerance = 2 * machine epsilon * abs(dt)

似乎也很好。下面的将适用于所有小数

var result = Math.round( Math.round(number1 * 100000) % Math.round(number2 * 100000) ) / 100000;

以下是一种方法:

function floatingPointAMultipleOfB(a, b) {
  const precision_a = getNumbersAfterDecimal(a)
  const precision_b = getNumbersAfterDecimal(b)

  if (precision_a > precision_b) return false;

  const int_a = Math.round(multBy10(a, precision_b))
  const int_b = Math.round(multBy10(b, precision_b))
  return int_a % int_b === 0
}


function getNumbersAfterDecimal(n) {
  const exponential = n.toString().split('e');
  if (exponential.length === 2) n = n.toFixed(Math.abs(exponential[1]))
  return (n.toString().split('.')[1] || []).length;
}

function multBy10(val, n) {
  if (n === 0) return val
  return multBy10(val, n-1) * 10
}

你对“的倍数”的容忍度是多少?为什么不把数字除以,然后检查你是否接近整数?同样重要的是要注意,这不是JavaScript的限制,而是二进制数表示的限制。相等比较和浮点不在一起,尤其是ieee(尤其是零)。您需要查看结果是否在有限的范围内,例如fabs(result)<0.001根本不使用浮点。在Smalltalk(最新的Squeak)中,我会说它像^((分数读取自:“1.0006”)/(分数读取自:“0.0002”)fractionPart=0一样简单。你离编程语言太远了though@Alexander:可能是我
tolerance = machine epsilon * max(abs(t), abs(dt)) / 2
tolerance = 2 * machine epsilon * abs(dt)
var result = Math.round( Math.round(number1 * 100000) % Math.round(number2 * 100000) ) / 100000;
function floatingPointAMultipleOfB(a, b) {
  const precision_a = getNumbersAfterDecimal(a)
  const precision_b = getNumbersAfterDecimal(b)

  if (precision_a > precision_b) return false;

  const int_a = Math.round(multBy10(a, precision_b))
  const int_b = Math.round(multBy10(b, precision_b))
  return int_a % int_b === 0
}


function getNumbersAfterDecimal(n) {
  const exponential = n.toString().split('e');
  if (exponential.length === 2) n = n.toFixed(Math.abs(exponential[1]))
  return (n.toString().split('.')[1] || []).length;
}

function multBy10(val, n) {
  if (n === 0) return val
  return multBy10(val, n-1) * 10
}