2022-10-01 23:10:44 +08:00
|
|
|
#include "unit.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
double Unit::FromString(QString string, QString unit, QString prefixes)
|
|
|
|
{
|
|
|
|
if(string.size() == 0) {
|
|
|
|
return std::numeric_limits<double>::quiet_NaN();
|
|
|
|
}
|
|
|
|
// remove unit if present
|
|
|
|
if(string.endsWith(unit, Qt::CaseInsensitive)) {
|
|
|
|
string.chop(unit.size());
|
|
|
|
}
|
|
|
|
// check if last char is a valid prefix
|
|
|
|
double factor = 1.0;
|
|
|
|
if(prefixes.contains(string.at(string.size()-1))) {
|
|
|
|
QChar prefix = string.at(string.size()-1);
|
|
|
|
factor = SIPrefixToFactor(prefix.toLatin1());
|
|
|
|
string.chop(1);
|
|
|
|
}
|
|
|
|
bool convertOk;
|
|
|
|
auto value = string.toDouble(&convertOk);
|
|
|
|
if(!convertOk) {
|
|
|
|
return std::numeric_limits<double>::quiet_NaN();
|
|
|
|
}
|
|
|
|
return value * factor;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Unit::ToString(double value, QString unit, QString prefixes, int precision)
|
|
|
|
{
|
|
|
|
// change label text
|
|
|
|
QString sValue;
|
|
|
|
if(isnan(value) || isinf(value)) {
|
|
|
|
sValue.append("NaN");
|
|
|
|
return sValue;
|
|
|
|
} else if(abs(value) <= numeric_limits<double>::epsilon()) {
|
|
|
|
sValue.append("0 ");
|
|
|
|
} else {
|
|
|
|
if(value < 0) {
|
|
|
|
sValue.append('-');
|
|
|
|
value = -value;
|
|
|
|
}
|
|
|
|
int prefixIndex = 0; //prefixes.indexOf(' ');
|
2023-04-05 23:13:21 +08:00
|
|
|
int preDotDigits = log10(value / SIPrefixToFactor(prefixes[prefixIndex].toLatin1())) + (1.0-log10(0.5));
|
2022-10-01 23:10:44 +08:00
|
|
|
while(preDotDigits > 3 && prefixIndex < prefixes.length() - 1) {
|
|
|
|
prefixIndex++;
|
|
|
|
preDotDigits = log10(value / SIPrefixToFactor(prefixes[prefixIndex].toLatin1())) + 1;
|
|
|
|
}
|
|
|
|
value /= SIPrefixToFactor(prefixes[prefixIndex].toLatin1());
|
|
|
|
stringstream ss;
|
|
|
|
ss << std::fixed;
|
|
|
|
if(precision < 0) {
|
|
|
|
precision = 0;
|
|
|
|
}
|
|
|
|
if(preDotDigits >= 0) {
|
|
|
|
if(precision - preDotDigits < 0) {
|
|
|
|
ss << std::setprecision(0);
|
|
|
|
} else {
|
|
|
|
ss << std::setprecision(precision - preDotDigits);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ss << std::setprecision(precision - 2);
|
|
|
|
}
|
|
|
|
ss << value;
|
|
|
|
sValue.append(QString::fromStdString(ss.str()));
|
|
|
|
sValue.append(prefixes[prefixIndex]);
|
|
|
|
}
|
|
|
|
sValue.append(unit);
|
|
|
|
return sValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Unit::SIPrefixToFactor(char prefix)
|
|
|
|
{
|
|
|
|
switch(prefix) {
|
|
|
|
case 'f': return 1e-15; break;
|
|
|
|
case 'p': return 1e-12; break;
|
|
|
|
case 'n': return 1e-9; break;
|
|
|
|
case 'u': return 1e-6; break;
|
|
|
|
case 'm': return 1e-3; break;
|
|
|
|
case ' ': return 1e0; break;
|
|
|
|
case 'k': return 1e3; break;
|
|
|
|
case 'M': return 1e6; break;
|
|
|
|
case 'G': return 1e9; break;
|
|
|
|
case 'T': return 1e12; break;
|
|
|
|
case 'P': return 1e15; break;
|
|
|
|
default: return 1e0; break;
|
|
|
|
}
|
|
|
|
}
|