From: Georg Baum Date: Thu, 14 May 2015 10:10:42 +0000 (+0200) Subject: Fix LaTeX length export of big numbers (bug 9416) X-Git-Tag: 2.2.0alpha1~847 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=59e4d16ab9611732dbc208f23d3de4b9da321dce;p=lyx.git Fix LaTeX length export of big numbers (bug 9416) LaTeX lengths must not use scientific notation, since the + sign has a different meaning (glue lengths). This is the export part of bug 9416, the GUI part is still not fixed. --- diff --git a/src/Length.cpp b/src/Length.cpp index 2463be8f66..89061e104b 100644 --- a/src/Length.cpp +++ b/src/Length.cpp @@ -22,6 +22,7 @@ #include "frontends/FontMetrics.h" #include "support/docstream.h" +#include "support/lstrings.h" #include #include @@ -81,29 +82,31 @@ docstring const Length::asDocstring() const string const Length::asLatexString() const { ostringstream os; + // Do not allow scientific notation (e.g. 1.2e+03), since this is not valid + // LaTeX (bug 9416) switch (unit_) { case PTW: - os << val_ / 100.0 << "\\textwidth"; + os << support::formatFPNumber(val_ / 100.0) << "\\textwidth"; break; case PCW: - os << val_ / 100.0 << "\\columnwidth"; + os << support::formatFPNumber(val_ / 100.0) << "\\columnwidth"; break; case PPW: - os << val_ / 100.0 << "\\paperwidth"; + os << support::formatFPNumber(val_ / 100.0) << "\\paperwidth"; break; case PLW: - os << val_ / 100.0 << "\\linewidth"; + os << support::formatFPNumber(val_ / 100.0) << "\\linewidth"; break; case PTH: - os << val_ / 100.0 << "\\textheight"; + os << support::formatFPNumber(val_ / 100.0) << "\\textheight"; break; case PPH: - os << val_ / 100.0 << "\\paperheight"; + os << support::formatFPNumber(val_ / 100.0) << "\\paperheight"; break; case UNIT_NONE: break; default: - os << val_ << unit_name[unit_]; + os << support::formatFPNumber(val_) << unit_name[unit_]; break; } return os.str(); diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp index ea1ba59984..f7e8b5aa3c 100644 --- a/src/support/lstrings.cpp +++ b/src/support/lstrings.cpp @@ -22,9 +22,12 @@ #include +#include #include #include #include +#include +#include #include using namespace std; @@ -1385,6 +1388,25 @@ int findToken(char const * const str[], string const & search_token) } +std::string formatFPNumber(double x) +{ + // Need manual tweaking, QString::number(x, 'f', 16) does not work either + ostringstream os; + os << std::fixed; + // Prevent outputs of 23.4200000000000017 but output small numbers + // with at least 6 significant digits. + double const logarithm = log10(x); + os << std::setprecision(max(6 - static_cast(round(logarithm)), 0)) << x; + string result = os.str(); + if (result.find('.') != string::npos) { + result = rtrim(result, "0"); + if (result[result.length()-1] == '.') + result = rtrim(result, "."); + } + return result; +} + + template<> docstring bformat(docstring const & fmt, int arg1) { diff --git a/src/support/lstrings.h b/src/support/lstrings.h index 0d21e954a4..395e18e04d 100644 --- a/src/support/lstrings.h +++ b/src/support/lstrings.h @@ -302,6 +302,15 @@ docstring const getStringFromVector(std::vector const & vec, /// found, else -1. The last item in \p str must be "". int findToken(char const * const str[], std::string const & search_token); + +/// Format a floating point number with at least 6 siginificant digits, but +/// without scientific notation. +/// Scientific notation would be invalid in some contexts, such as lengths for +/// LaTeX. Simply using std::ostream with std::fixed would produce results +/// like "1000000.000000", and precision control would not be that easy either. +std::string formatFPNumber(double); + + template docstring bformat(docstring const & fmt, Arg1); diff --git a/src/support/tests/check_lstrings.cpp b/src/support/tests/check_lstrings.cpp index 3509e45e89..b759f6a2e7 100644 --- a/src/support/tests/check_lstrings.cpp +++ b/src/support/tests/check_lstrings.cpp @@ -25,8 +25,59 @@ void test_uppercase() cout << uppercase('a') << endl; } +void test_formatFPNumber() +{ + cout << formatFPNumber(0) << endl; + cout << formatFPNumber(1) << endl; + cout << formatFPNumber(23.42) << endl; + cout << formatFPNumber(1.3754937356458394574047e-20) << endl; + cout << formatFPNumber(1.3754937356458394574047e-19) << endl; + cout << formatFPNumber(1.3754937356458394574047e-18) << endl; + cout << formatFPNumber(1.3754937356458394574047e-17) << endl; + cout << formatFPNumber(1.3754937356458394574047e-16) << endl; + cout << formatFPNumber(1.3754937356458394574047e-15) << endl; + cout << formatFPNumber(1.3754937356458394574047e-14) << endl; + cout << formatFPNumber(1.3754937356458394574047e-13) << endl; + cout << formatFPNumber(1.3754937356458394574047e-12) << endl; + cout << formatFPNumber(1.3754937356458394574047e-11) << endl; + cout << formatFPNumber(1.3754937356458394574047e-10) << endl; + cout << formatFPNumber(1.3754937356458394574047e-9) << endl; + cout << formatFPNumber(1.3754937356458394574047e-8) << endl; + cout << formatFPNumber(1.3754937356458394574047e-7) << endl; + cout << formatFPNumber(1.3754937356458394574047e-6) << endl; + cout << formatFPNumber(1.3754937356458394574047e-5) << endl; + cout << formatFPNumber(1.3754937356458394574047e-4) << endl; + cout << formatFPNumber(1.3754937356458394574047e-3) << endl; + cout << formatFPNumber(1.3754937356458394574047e-2) << endl; + cout << formatFPNumber(1.3754937356458394574047e-1) << endl; + cout << formatFPNumber(1.3754937356458394574047) << endl; + cout << formatFPNumber(1.3754937356458394574047e1) << endl; + cout << formatFPNumber(1.3754937356458394574047e2) << endl; + cout << formatFPNumber(1.3754937356458394574047e3) << endl; + cout << formatFPNumber(1.3754937356458394574047e4) << endl; + cout << formatFPNumber(1.3754937356458394574047e5) << endl; + cout << formatFPNumber(1.3754937356458394574047e6) << endl; + cout << formatFPNumber(1.3754937356458394574047e7) << endl; + cout << formatFPNumber(1.3754937356458394574047e8) << endl; + cout << formatFPNumber(1.3754937356458394574047e9) << endl; + cout << formatFPNumber(1.3754937356458394574047e10) << endl; + cout << formatFPNumber(1.3754937356458394574047e11) << endl; + cout << formatFPNumber(1.3754937356458394574047e12) << endl; + cout << formatFPNumber(1.3754937356458394574047e13) << endl; + cout << formatFPNumber(1.3754937356458394574047e14) << endl; + cout << formatFPNumber(1.3754937356458394574047e15) << endl; + cout << formatFPNumber(1.3754937356458394574047e16) << endl; + cout << formatFPNumber(1.3754937356458394574047e17) << endl; + cout << formatFPNumber(1.3754937356458394574047e18) << endl; + cout << formatFPNumber(1.3754937356458394574047e19) << endl; + cout << formatFPNumber(1.3754937356458394574047e20) << endl; + cout << formatFPNumber(1e-42) << endl; + cout << formatFPNumber(1e42) << endl; +} + int main() { test_lowercase(); test_uppercase(); + test_formatFPNumber(); } diff --git a/src/support/tests/regfiles/lstrings b/src/support/tests/regfiles/lstrings index cc2481b504..20363cd0c8 100644 --- a/src/support/tests/regfiles/lstrings +++ b/src/support/tests/regfiles/lstrings @@ -5,3 +5,49 @@ alle A ALLE A +0 +1 +23.42 +0.00000000000000000001375494 +0.0000000000000000001375494 +0.000000000000000001375494 +0.00000000000000001375494 +0.0000000000000001375494 +0.000000000000001375494 +0.00000000000001375494 +0.0000000000001375494 +0.000000000001375494 +0.00000000001375494 +0.0000000001375494 +0.000000001375494 +0.00000001375494 +0.0000001375494 +0.000001375494 +0.00001375494 +0.0001375494 +0.001375494 +0.01375494 +0.1375494 +1.375494 +13.75494 +137.5494 +1375.494 +13754.94 +137549.4 +1375494 +13754937 +137549374 +1375493736 +13754937356 +137549373565 +1375493735646 +13754937356458 +137549373564584 +1375493735645840 +13754937356458394 +137549373564583952 +1375493735645839360 +13754937356458393600 +137549373564583952384 +0.000000000000000000000000000000000000000001 +1000000000000000044885712678075916785549312