比较Javascript中的十进制字符串
我有两个字符串的输入,每个字符串表示十进制格式的非负有理数 给定这两个字符串比较Javascript中的十进制字符串,javascript,node.js,string,floating-point,numbers,Javascript,Node.js,String,Floating Point,Numbers,我有两个字符串的输入,每个字符串表示十进制格式的非负有理数 给定这两个字符串x和y,我想检查x表示的数值是否大于y表示的数值 这两个值可以非常大,也可以扩展到非常高的精度(即小数点后的许多数字) 因此,我不能依靠Number(x)>Number(y)来完成这项工作 相反,我实现了以下功能: function isLarger(x, y) { const xParts = x.split(".").concat(""); const yParts = y.split(".").co
x
和y
,我想检查x
表示的数值是否大于y
表示的数值
这两个值可以非常大,也可以扩展到非常高的精度(即小数点后的许多数字)
因此,我不能依靠Number(x)>Number(y)
来完成这项工作
相反,我实现了以下功能:
function isLarger(x, y) {
const xParts = x.split(".").concat("");
const yParts = y.split(".").concat("");
xParts[0] = xParts[0].padStart(yParts[0].length, "0");
yParts[0] = yParts[0].padStart(xParts[0].length, "0");
xParts[1] = xParts[1].padEnd (yParts[1].length, "0");
yParts[1] = yParts[1].padEnd (xParts[1].length, "0");
return xParts.join("").localeCompare(yParts.join("")) == 1;
}
我进行了广泛的测试,通过生成随机输入x
和y
,并将isLarger(x,y)
的结果与表达式Number(x)>Number(y)
的值进行比较
当然,出于上述原因,我不能依赖表达式Number(x)>Number(y)
的值来纠正每个可能的输入x
和y
因此,我想就上述功能获得一些反馈:
- 里面有什么警告吗
- 有没有更简单的方法来实现这一点
- 我看不出您的解决方案中有任何警告,但最后一行不必要地复杂。而不是
返回xParts.join(“”).localeCompare(yParts.join(“”))==1代码>
您可以简单地使用以下内容:
返回xParts.join(“”)>yParts.join(“”)代码>
对输入值有一些限制的更简单的解决方案
如果您可以绝对确定您的输入永远不会包含不必要的前导零的数字(例如001
而不是1
)或以点开头的十进制数字(例如.1
而不是0.1
)通过首先比较整数部分中的位数,可以显著简化比较
整数部分的位数越多表示数字越大,位数越少表示数字越小
当整数位数相同时,简单的字符串比较基本上就足够了。如果x
等于y
,但包含更多的尾随零(因为'211.00'>'211.0'
为true
),则只需要一个填充操作-y
需要用尾随零填充,以避免得到真实的结果
我对你的测试方法有个警告。根据我对问题和评论的理解,我实施了它。为了测试测试方法,我在isLarger
中引入了一个严重错误,完全忽略了小数点后的部分
即使有如此严重的错误,我在10000000次运行中也有5次失败,相当于每百万次运行中有0.5次失败
我认为你需要一个测试方法,在更多的情况下,部分数字匹配
这是我的节目:
function isLarger(x, y) {
const xParts = x.split(".").concat("");
const yParts = y.split(".").concat("");
xParts[0] = xParts[0].padStart(yParts[0].length, "0");
yParts[0] = yParts[0].padStart(xParts[0].length, "0");
xParts[1] = xParts[1].padEnd(yParts[1].length, "0");
yParts[1] = yParts[1].padEnd(xParts[1].length, "0");
xParts[1] = "";
yParts[1] = "";
return xParts.join("").localeCompare(yParts.join("")) == 1;
}
function testIt(x, y) {
const actual = isLarger(x, y);
const expected = Number(x) > Number(y);
if (actual != expected) {
console.log("x=" + x + " y=" + y + " actual " + actual + " expected "
+ expected);
}
}
function randAsString() {
return (Math.random() * 1000000).toString();
}
testIt("3.3", "3.2");
for (var i = 0; i < 10000000; i++) {
testIt(randAsString(), randAsString());
}
函数isLarger(x,y){
const xParts=x.split(“.”)。concat(“”);
const yParts=y.split(“.”)。concat(“”);
xParts[0]=xParts[0]。焊盘起始(yParts[0]。长度,“0”);
yParts[0]=yParts[0]。焊盘起始(xParts[0]。长度,“0”);
xParts[1]=xParts[1]。焊盘端(yParts[1]。长度,“0”);
yParts[1]=yParts[1]。焊盘端(xParts[1]。长度,“0”);
xParts[1]=“”;
yParts[1]=“”;
返回xParts.join(“”).localeCompare(yParts.join(“”)==1;
}
功能测试(x,y){
实际常数=isLarger(x,y);
预期常数=数量(x)>数量(y);
如果(实际!=预期){
console.log(“x=“+x+”y=“+y+”实际值“+实际值+”预期值”
+预期);
}
}
函数randaString(){
return(Math.random()*1000000.toString();
}
测试(“3.3”、“3.2”);
对于(变量i=0;i<10000000;i++){
testIt(randaString(),randaString());
}
你有一些关于结果的例子吗?@NinaScholz:我多次调用它,将x
和y
设置为(Math.random()*1000000)。toString()
。然后将其输出与Number(x)>Number(y)
进行比较。结果似乎总是成立的,但就像我说的-我怎么能相信编号(x)>编号(y)
?另外,正如您所看到的,我生成的输入没有包含非常大的值。我没有看到任何即时的警告。有一些库可以处理大小数,比如,但不知道它们在性能上与您的实现相比如何。@RobbyCornelissen:谢谢。我试图避免使用BigNumber.js
和Decimal.js
,并将其保存在“原生”js中。您肯定可以稍微优化一下实现。例如,仅比较整数部分的长度可能会消除许多后续的填充和字符串比较。谢谢。是否确定返回xParts.join(“”>yParts.join(“”)代码>?@goodvibration是的,我确信这一点。请参阅JS中字符串的简单比较。(如果不信任随机源,请参阅。)localeCompare
用于对字符串进行特殊的区域设置感知字母顺序比较(以确保例如a
位于b
之前,即使其代码点值不在前面)@goodvibration我已编辑代码,以说明y不包含小数点的可能性。(我的原始代码返回了x=20.1
和y=20
的错误结果,因为y被填充到2000
,而不是20.0
和。
小于'0'
)。谢谢。我只修改了您的xParts.join(“”>yParts.join(“”)建议,因为如果我的原始代码中没有任何警告,那么我希望尽可能简单(如果需要,在性能方面)。谢谢
function isLarger(x, y) {
const xParts = x.split(".").concat("");
const yParts = y.split(".").concat("");
xParts[0] = xParts[0].padStart(yParts[0].length, "0");
yParts[0] = yParts[0].padStart(xParts[0].length, "0");
xParts[1] = xParts[1].padEnd(yParts[1].length, "0");
yParts[1] = yParts[1].padEnd(xParts[1].length, "0");
xParts[1] = "";
yParts[1] = "";
return xParts.join("").localeCompare(yParts.join("")) == 1;
}
function testIt(x, y) {
const actual = isLarger(x, y);
const expected = Number(x) > Number(y);
if (actual != expected) {
console.log("x=" + x + " y=" + y + " actual " + actual + " expected "
+ expected);
}
}
function randAsString() {
return (Math.random() * 1000000).toString();
}
testIt("3.3", "3.2");
for (var i = 0; i < 10000000; i++) {
testIt(randAsString(), randAsString());
}