From 604c1b158ceb01bff6be49dc8e1b04519a1c8fb7 Mon Sep 17 00:00:00 2001 From: Mickey Phoenix Date: Wed, 12 Jul 2017 13:49:10 -0700 Subject: [PATCH] Fix documentation for folly's to() method's handling of 'NaN' and unparseable inputs Summary: The documentation for folly::to()'s handling of unparseable inputs (including "") is incorrect. Additionally, the documentation does not document to()'s handling of the inputs "NaN", "-NaN", "inf", "infinity", "-inf", and "-infinity". This corrects the documentation. See https://github.com/facebook/folly/blob/3272dfdbe243e0ac02acca1dd82bc391d1da079a/folly/docs/Conv.md under the heading "Parsing floating-point types" for the incorrect documentation as rendered. Reviewed By: yfeldblum Differential Revision: D5367656 fbshipit-source-id: 22b38e2bb85d2e647975798360ead39eed6caae8 --- folly/docs/Conv.md | 52 ++++++++++++++++++++++++++++++++++++++--- folly/test/ConvTest.cpp | 18 ++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/folly/docs/Conv.md b/folly/docs/Conv.md index 7156c116..22add9e1 100644 --- a/folly/docs/Conv.md +++ b/folly/docs/Conv.md @@ -205,17 +205,63 @@ routine that works faster than `to` chances are it is incorrect and will fail in a variety of corner cases. Using `to` is strongly recommended. -Note that if an unparsable string is passed to `to` `NaN` -is returned, which can be tested for as follows: +Note that if the string "NaN" (with any capitalization) is passed to +`to` then `NaN` is returned, which can be tested for as follows: ``` Cpp - fbstring str = "not a double"; + fbstring str = "nan"; // "NaN", "NAN", etc. double d = to(str); if (std::isnan(d)) { + // string was a valid representation of the double value NaN + } +``` + +Note that passing "-NaN" (with any capitalization) to `to` also returns +`NaN`. + +Note that if the strings "inf" or "infinity" (with any capitalization) are +passed to `to` then `infinity` is returned, which can be tested for +as follows: + +``` Cpp + fbstring str = "inf"; // "Inf", "INF", "infinity", "Infinity", etc. + double d = to(str); + if (std::isinf(d)) { + // string was a valid representation of one of the double values +Infinity + // or -Infinity + } +``` + +Note that passing "-inf" or "-infinity" (with any capitalization) to +`to` returns `-infinity` rather than `+infinity`. The sign of the +`infinity` can be tested for as follows: + +``` Cpp + fbstring str = "-inf"; // or "inf", "-Infinity", "+Infinity", etc. + double d = to(str); + if (d == std::numeric_limits::infinity()) { + // string was a valid representation of the double value +Infinity + } else if (d == -std::numeric_limits::infinity()) { + // string was a valid representation of the double value -Infinity + } +``` + +Note that if an unparseable string is passed to `to` then an exception +is thrown, rather than `NaN` being returned. This can be tested for as follows: + +``` Cpp + fbstring str = "not-a-double"; // Or "1.1.1", "", "$500.00", etc. + double d; + try { + d = to(str); + } catch (const std::range_error &) { // string could not be parsed } ``` +Note that the empty string (`""`) is an unparseable value, and will cause +`to` to throw an exception. + #### Non-throwing interfaces `tryTo` is the non-throwing variant of `to`. It returns diff --git a/folly/test/ConvTest.cpp b/folly/test/ConvTest.cpp index 646f8a13..3d5d0f63 100644 --- a/folly/test/ConvTest.cpp +++ b/folly/test/ConvTest.cpp @@ -605,12 +605,30 @@ TEST(Conv, StringPieceToDouble) { } catch (const std::range_error &) { } + EXPECT_TRUE(std::isnan(to("nan"))); EXPECT_TRUE(std::isnan(to("NaN"))); + EXPECT_TRUE(std::isnan(to("NAN"))); + EXPECT_TRUE(std::isnan(to("-nan"))); + EXPECT_TRUE(std::isnan(to("-NaN"))); + EXPECT_TRUE(std::isnan(to("-NAN"))); + EXPECT_EQ(to("inf"), numeric_limits::infinity()); + EXPECT_EQ(to("Inf"), numeric_limits::infinity()); + EXPECT_EQ(to("INF"), numeric_limits::infinity()); + EXPECT_EQ(to("inF"), numeric_limits::infinity()); EXPECT_EQ(to("infinity"), numeric_limits::infinity()); + EXPECT_EQ(to("Infinity"), numeric_limits::infinity()); + EXPECT_EQ(to("INFINITY"), numeric_limits::infinity()); + EXPECT_EQ(to("iNfInItY"), numeric_limits::infinity()); EXPECT_THROW(to("infinitX"), std::range_error); EXPECT_EQ(to("-inf"), -numeric_limits::infinity()); + EXPECT_EQ(to("-Inf"), -numeric_limits::infinity()); + EXPECT_EQ(to("-INF"), -numeric_limits::infinity()); + EXPECT_EQ(to("-inF"), -numeric_limits::infinity()); EXPECT_EQ(to("-infinity"), -numeric_limits::infinity()); + EXPECT_EQ(to("-Infinity"), -numeric_limits::infinity()); + EXPECT_EQ(to("-INFINITY"), -numeric_limits::infinity()); + EXPECT_EQ(to("-iNfInItY"), -numeric_limits::infinity()); EXPECT_THROW(to("-infinitX"), std::range_error); } -- 2.34.1