为什么Ruby错误地解析带有逗号作为浮点数的字符串?

为什么Ruby错误地解析带有逗号作为浮点数的字符串?,ruby,floating-point,Ruby,Floating Point,我的问题的关键是: irb(main):001:0> "5,280".to_f => 5.0 Ruby为什么这么做 我几乎可以理解5280.to_I==5,因为,在某些地区是十进制类型的定界符,但这里的精度损失让我感到困惑,特别是因为5.280.to_f按预期返回5.28 这只是一个bug吗 Ruby版本,以备不时之需: $ ruby --version ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-dar

我的问题的关键是:

irb(main):001:0> "5,280".to_f
=> 5.0
Ruby为什么这么做

我几乎可以理解5280.to_I==5,因为,在某些地区是十进制类型的定界符,但这里的精度损失让我感到困惑,特别是因为5.280.to_f按预期返回5.28

这只是一个bug吗

Ruby版本,以备不时之需:

$ ruby --version
ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin17]
从这句话中,我们可以说同样的话:

托福→ 浮动 返回将str中的前导字符解释为浮点数的结果。超过有效数字结尾的无关字符将被忽略。如果str开头没有有效数字,则返回0.0。此方法从不引发异常

所以5280.to_f做的正是它应该做的。所有字符(不包括逗号)都是有效数字,在本例中,多余字符280将被忽略。结果与调用“5”的结果相同

这不是一个bug,而是预期的和记录的行为。这是Stringto_f的行为,至少从那时开始。

但是说的是同样的事情:

托福→ 浮动 返回将str中的前导字符解释为浮点数的结果。超过有效数字结尾的无关字符将被忽略。如果str开头没有有效数字,则返回0.0。此方法从不引发异常

所以5280.to_f做的正是它应该做的。所有字符(不包括逗号)都是有效数字,在本例中,多余字符280将被忽略。结果与调用“5”的结果相同


这不是一个bug,而是预期的和记录的行为。这至少是Stringto\u f的行为。

我不认为这是一个bug,我认为这与Ruby调用\u f时考虑的字符串部分有关

Ruby查看从左边开始的字符串,以及0-9的任何字符、第一个小数点和后面0-9的字符,它将匹配并尝试转换为浮点。任何右边的都会被忽略

如果没有与该条件匹配的字符,则返回0.0

示例:

>>'5.5'.to_f 
=> 5.5

>>'5.5stuff'.to_f 
=> 5.5   

>>'5.stuff5'.to_f 
=> 5.0

>>'5,5'.to_f 
=> 5.0

>>'stuff5.5'.to_f 
=> 0.0

我不认为这是一个bug,我认为这与Ruby调用f时考虑的字符串部分有关

Ruby查看从左边开始的字符串,以及0-9的任何字符、第一个小数点和后面0-9的字符,它将匹配并尝试转换为浮点。任何右边的都会被忽略

如果没有与该条件匹配的字符,则返回0.0

示例:

>>'5.5'.to_f 
=> 5.5

>>'5.5stuff'.to_f 
=> 5.5   

>>'5.stuff5'.to_f 
=> 5.0

>>'5,5'.to_f 
=> 5.0

>>'stuff5.5'.to_f 
=> 0.0
Ruby只需调用strtod C函数

它有如下功能:

/*
 * Count the number of digits in the mantissa (including the decimal
 * point), and also locate the decimal point.
 */

decPt = -1;
for (mantSize = 0; ; mantSize += 1)
{
c = *p;
if (!isdigit(c)) {
    if ((c != '.') || (decPt >= 0)) {
    break;
    }
    decPt = mantSize;
}
p += 1;
}
根据if c!='。||decPt>=0{ 打破 如果发现任何非点符号,则strtod停止,例如:

irb(main):002:0> "2;58".to_f
=> 2.0
irb(main):003:0> "2@58".to_f
=> 2.0
irb(main):004:0> 
UPD:这种方法适用于mri 2.6 ruby实现。在其他版本/实现中可能会有所不同。

ruby只需调用strtod C函数即可

strtod函数有如下功能:

/*
 * Count the number of digits in the mantissa (including the decimal
 * point), and also locate the decimal point.
 */

decPt = -1;
for (mantSize = 0; ; mantSize += 1)
{
c = *p;
if (!isdigit(c)) {
    if ((c != '.') || (decPt >= 0)) {
    break;
    }
    decPt = mantSize;
}
p += 1;
}
根据如果c!='.| | decPt>=0{ 打破 如果发现任何非点符号,则strtod停止,例如:

irb(main):002:0> "2;58".to_f
=> 2.0
irb(main):003:0> "2@58".to_f
=> 2.0
irb(main):004:0> 

UPD:这种方法适用于mri 2.6 ruby实现。在其他版本/实现中可能会有所不同。

您希望5280.to_f返回什么?to_i和to_f在转换时非常懒惰和允许。如果您希望通过错误检查实现健壮的转换,请使用float5DJFSDKJFHS.to_f返回什么?可能是ei它们会引发错误,或者做出最佳猜测,然后返回5.0。这也正是这里发生的情况。在字符串和数字之间转换时,Ruby不会尝试猜测区域设置;字符串只能包含数字,或者。对于小数点。@Two bitalchest Maybe。或者,正如Ruby语言设计师所选择的,to_f应该是b这是一个安全的操作,它总是返回一个浮点数,从不出错。返回nil不会是胡说八道吗?即使nil.to\u f==0?好的。每个都有自己的。你期望5280.to\u f返回什么?to\u i和to\u f在转换时是非常懒惰和宽容的。如果你想通过错误检查实现健壮的转换,使用float5djf应该做什么sdkjfhs.to_f return?它可能会引发错误,或者做出最佳猜测,然后返回5.0。这也正是这里发生的情况。在字符串和数字之间转换时,Ruby不会尝试猜测区域设置;字符串只能包含数字,或者。对于小数点。@2位炼金术士可能。或者,作为Ruby语言设计者选择,to_f应该是一个安全的操作,它总是返回一个浮点并且从不出错。to_f返回nil不会是胡说八道吗?即使nil.to_f==0?好的。每个人都有自己的。这只适用于你正在查看的特定版本的MRI。但不能保证每个版本的Ruby都会使用libc的strod,而不是all版本的Ruby甚至可以用C.T编写
他说Stringto_f的行为有一定的方式,MRI中的具体实现是偶然的。谢谢,我在我的回答中添加了关于这一点的注释。这只适用于您正在查看的特定版本的MRI。不能保证每个版本的Ruby都会使用libc的strtod,甚至不是所有版本的Ruby都会用C编写。文档中说Stringto_f的行为是特定的,MRI中的具体实现是偶然的。谢谢,我在回答中补充了这一点。