为什么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中的具体实现是偶然的。谢谢,我在回答中补充了这一点。