[QGIS-Developer] On precision in qgsRound() (3.3.0 master)
andreaerdna
andreaerdna at libero.it
Tue Sep 11 09:04:48 PDT 2018
Nyall Dawson wrote
> On Mon, 10 Sep 2018 at 20:04, andreaerdna <
> andreaerdna@
> > wrote:
>> 'scaleFactor' should be qlonglong in order to correctly store at least
>> the
>> 12th power of 10
>
> Yes, that looks correct! Can you open a PR with a test case fixing this?
I'm not sure if this simple fix could completely solve the problem in the
right way, avoiding any overflow.
Taking better account of any side effects:
now in QGIS 3.3.0 master, as said,
'scaleFactor' defined as Int overflows when 'places' > 9, leading to
incorrect rounding,
while static_cast<qlonglong>((number * scaleFactor) + 0.5) and the whole
'result' already overflow when 'number', the measure to round, is at least
about:
places = 8 -> 92'233'720'369 units
places = 9 -> 9'223'372'037 units (see overflow in action [1])
places >= 10 -> 4'294'967'296 units (see [2])
instead, with the "fix" [3],
'scaleFactor' defined as qlonglong doesn't overflow at all for 'places' <=
12 (actually <=19)
but then static_cast<qulonglong>((number * scaleFactor) + 0.5) overflows
when 'number' is at least about:
places = 8 -> 184'467'440'738 units (better then now)
places = 9 -> 18'446'744'074 units (better)
places = 10 -> 1'844'674'408 units (worse)
places = 11 -> 184'467'441 units (worse)
places = 12 -> 18'446'745 units (worse)
I can not fully understand the reasons [4,5] that led to rewrite qgsRound(),
introduce scaledDistance/scaledArea and modify formatDistance/formatArea,
anywayI think now it could be better to:
- completely avoid to use qgsRound() in scaledDistance/scaledArea and rely
only on QStringLiteral().arg() in formatDistance/formatArea to correctly
round the measurements value [6]
or
- reduce to 9 (or less) the maximum precision value allowed to be set in
Setting->Options->Map Tools and in Project Properties->General [7]
or
- introduce some kind of logic in qgsRound() to handle and prevent overflows
or
- (?)
Some tests are needed, but I can not do them all by myself for now.
[1] https://agiudiceandrea.github.io/QGIS330_5.PNG
[2] https://agiudiceandrea.github.io/QGIS330_4.PNG
[3]
https://github.com/agiudiceandrea/QGIS/commit/7c16a409c911eef415f286a2af530c0163a04b26
[4] "Introduce qgsRound since std::round is available only in C++11 onwards"
https://github.com/qgis/QGIS/pull/2367
[5] "Modularize distance and area formatting"
https://github.com/qgis/QGIS/pull/4213
[6]
https://github.com/agiudiceandrea/QGIS/commit/54d719d38bc823ab5f9a2d5d47d3d52b82599b43
[7]
https://github.com/agiudiceandrea/QGIS/commit/8cc0b358a479f10edea8956700b5548691404d80
-----
Andrea Giudiceandrea
--
Sent from: http://osgeo-org.1560.x6.nabble.com/QGIS-Developer-f4099106.html
More information about the QGIS-Developer
mailing list