PDA

View Full Version : QVector.append rounding values



splinterz
9th July 2014, 02:28
i have a function that returns a double value (eg. 1.76896558753375)

then i append the value to a QVector<double> with some_vector.append(value)

after append, the value is 1.76897 in the qvector.

why is this happening and how can it be prevented?

stepping through qvector's append function:


template <typename T>
void QVector<T>::append(const T &t)
{
const T copy(t);
const bool isTooSmall = uint(d->size + 1) > d->alloc;
if (!isDetached() || isTooSmall) {
QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
}
if (QTypeInfo<T>::isComplex)
new (d->end()) T(copy);
else
*d->end() = copy;
++d->size;
}


both t and copy are the correct un-rounded value until ++d->size, after that line, the rounded value is appended instead of the full value.

stampede
9th July 2014, 10:50
How do you test that ? If by printing it to qDebug, then it is not a reliable way :)


#include <QVector>
#include <QDebug>

int main(int argc, char ** argv){
const double test_value = 1.76896558753375;
QVector<double> vec;
vec.append(test_value);
const double from_vec = vec.at(0);
if (qFuzzyCompare(from_vec,test_value))
qDebug() << "OK";
else
qDebug() << "ERROR!";
qDebug() << vec;
qDebug() << qSetRealNumberPrecision(15) << vec;
return 0;
}

output:


OK
QVector(1.76897)
QVector(1.76896558753375)

Tested with Qt 4.8, gcc 4.5.2 and 5.1.1, gcc 4.8, windows 8
Can you run this example on your machine and post the output ?

splinterz
9th July 2014, 11:06
you're correct, it does print the full value with qSetRealNumberPrecision! i was using the debugger to check the values. ok so the problem then is with comparison i guess..

after the values are inserted into the vector, the vector is used with std::upper_bound and std::lower_bound to find the original value, and that's where the problem is. upper/lower bound aren't returning the position of the double in the qvector.



//b = list.begin();
//e = list.end();
//n = list.size();
double get_upper_bound(double x) const
{
QVector<double>::Iterator it = upper_bound(b,e,x);
unsigned pos = it-b; // find the first element >= x. this is the issue, pos sometimes returns 0 instead of the proper location in the qvector
return (pos/n);
}

stampede
9th July 2014, 11:43
Can you post a minimal compilable example (sth. like in my post above) of std::upper_bound returning wrong position ?

splinterz
9th July 2014, 13:08
thanks for your patience stampede, but i've finally resolved this. the double that was passed to the original qvector for the upper_bound was passed to another function first... and that function had a float type as the parameter instead of a double. so the double->float->double conversion was altering the precision understandably. :(