diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index c847179f..a6162821 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -848,7 +848,7 @@ void UnitConverter::Calculate() } unordered_map conversionTable = m_ratioMap[m_fromType]; - if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)) + if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)) { m_returnDisplay = m_currentDisplay; m_returnHasDecimal = m_currentHasDecimal; @@ -858,50 +858,41 @@ void UnitConverter::Calculate() { double currentValue = stod(m_currentDisplay); double returnValue = Convert(currentValue, conversionTable[m_toType]); - m_returnDisplay = RoundSignificant(returnValue, MAXIMUMDIGITSALLOWED); - TrimString(m_returnDisplay); - int numPreDecimal = (int)m_returnDisplay.size(); - if (m_returnDisplay.find(L'.') != m_returnDisplay.npos) - { - numPreDecimal = (int)m_returnDisplay.find(L'.'); - } - if (returnValue < 0) - { - numPreDecimal--; - } - if (numPreDecimal > MAXIMUMDIGITSALLOWED || (returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED)) + auto isCurrencyConverter = m_currencyDataLoader != nullptr && m_currencyDataLoader->SupportsCategory(this->m_currentCategory); + if (isCurrencyConverter) { - wstringstream out(wstringstream::out); - out << scientific << returnValue; - m_returnDisplay = out.str(); + // We don't need to trim the value when it's a currency. + m_returnDisplay = RoundSignificant(returnValue, MAXIMUMDIGITSALLOWED); + TrimString(m_returnDisplay); } else { - returnValue = stod(m_returnDisplay); - - auto currentDisplayTrimmed = m_currentDisplay; - TrimString(currentDisplayTrimmed); - int currentNumberSignificantDigits = static_cast(currentDisplayTrimmed.size()); - if (currentDisplayTrimmed.find(L'.') != currentDisplayTrimmed.npos) - --currentNumberSignificantDigits; - if (currentValue < 0) - --currentNumberSignificantDigits; - - int precision = 0; - if (abs(returnValue) < OPTIMALDECIMALALLOWED) + int numPreDecimal = returnValue == 0 ? 0 : (1 + (int)log10(abs(returnValue))); + if (numPreDecimal > MAXIMUMDIGITSALLOWED || (returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED)) { - precision = MAXIMUMDIGITSALLOWED; + wstringstream out(wstringstream::out); + out << scientific << returnValue; + m_returnDisplay = out.str(); } else { - precision = max(0, max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits)) - numPreDecimal); + int currentNumberSignificantDigits = GetNumberSignificantDigits(m_currentDisplay); + int precision = 0; + if (abs(returnValue) < OPTIMALDECIMALALLOWED) + { + precision = MAXIMUMDIGITSALLOWED; + } + else + { + precision = max(0, max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits)) - numPreDecimal); + } + + m_returnDisplay = RoundSignificant(returnValue, precision); + TrimString(m_returnDisplay); } - - m_returnDisplay = RoundSignificant(returnValue, precision); - TrimString(m_returnDisplay); + m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); } - m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); } UpdateViewModel(); } @@ -910,9 +901,9 @@ void UnitConverter::Calculate() /// Trims out any trailing zeros or decimals in the given input string /// /// wstring to trim -void UnitConverter::TrimString(wstring& returnString) +void UnitConverter::TrimString(_Inout_ wstring& returnString) { - if (returnString.find(L'.') == m_returnDisplay.npos) + if (returnString.find(L'.') == returnString.npos) { return; } @@ -932,6 +923,24 @@ void UnitConverter::TrimString(wstring& returnString) } } +/// +/// Get number of significant digits (integer part + fractional part) of a number +/// the number +unsigned int UnitConverter::GetNumberSignificantDigits(std::wstring value) +{ + TrimString(value); + int currentNumberSignificantDigits = value.size(); + if (value.find(L'.') != value.npos) + { + --currentNumberSignificantDigits; + } + if (value.find(L'-') != value.npos) + { + --currentNumberSignificantDigits; + } + return currentNumberSignificantDigits; +} + /// /// Rounds the given double to the given number of significant digits /// diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h index 19582245..58712386 100644 --- a/src/CalcManager/UnitConverter.h +++ b/src/CalcManager/UnitConverter.h @@ -279,9 +279,7 @@ namespace UnitConversionManager double Convert(double value, ConversionData conversionData); std::vector> CalculateSuggested(); void ClearValues(); - void TrimString(std::wstring& input); void InitializeSelectedUnits(); - std::wstring RoundSignificant(double num, int numSignificant); Category StringToCategory(const std::wstring& w); std::wstring CategoryToString(const Category& c, const wchar_t* delimiter); std::wstring UnitToString(const Unit& u, const wchar_t* delimiter); @@ -292,6 +290,10 @@ namespace UnitConversionManager std::shared_ptr GetDataLoaderForCategory(const Category& category); std::shared_ptr GetCurrencyConverterDataLoader(); + static void TrimString(_Inout_ std::wstring& input); + static unsigned int GetNumberSignificantDigits(std::wstring value); + static std::wstring RoundSignificant(double num, int numSignificant); + private: std::shared_ptr m_dataLoader; std::shared_ptr m_currencyDataLoader;