преобразование из 'size_t' в 'const double', возможная потеря данных - PullRequest
1 голос
/ 06 февраля 2020

Учитывая переменную size_t idx, присваивание, подобное double value = idx;, выдает следующее предупреждение при компиляции под 64-битную версию:

'initializing': conversion from 'size_t' to 'double', possible loss of data

Похоже, что это связано с тем, что size_t значение занимает 8 байт при компиляции под 64 бит. Однако присвоение double value = static_cast<double>(idx) не выдает никаких предупреждений. Может кто-нибудь объяснить мне, почему первое назначение не работает, а второе работает?

Заранее спасибо!

Ответы [ 5 ]

3 голосов
/ 06 февраля 2020

Когда вы делаете

double value = idx;

Компилятор смотрит на это и говорит: «Эй, idx может не вместиться в value, давайте сообщим программисту, если это было ошибкой ".. Вот почему вы получаете предупреждение.

Когда вы делаете

double value = static_cast<double>(idx)

Компилятор смотрит на это и говорит: «О, программист явно приводит здесь, это должно быть то, что они хотят ".. Это означает, что предупреждение не появится.

2 голосов
/ 06 февраля 2020

static_cast<double> - это то, как вы сообщаете компилятору, что вы сознательно конвертируете в double и знаете обо всех последствиях. Это означает, что компилятор не должен предупреждать вас о рисках, потому что вы явно сказали, что уже знаете о них.

В первом случае, когда вы не используете static_cast, преобразование является законным, но несет в себе риск потери точности. Поскольку возможно, что вы не заметили, что это преобразование происходило, имеет смысл предупредить вас об этом.

2 голосов
/ 06 февраля 2020

Оба задания будут «работать» и, по сути, будут делать одно и то же! Единственное отличие состоит в том, что во втором случае, double value = static_cast<double>(idx), ваше явное приведение дает понять компилятору, что вы "знаете, что делаете" и что при преобразовании вы можете потерять значительные цифры.

В первом случае компилятор просто предупреждает вас, что ваше преобразование может (непреднамеренно) привести к потере данных (или точности, в данном случае).

0 голосов
/ 06 февраля 2020

64-битный дубль использует только 52 бита для хранения числа, а остальные для хранения знака (+ или -) и показателя степени. ( Примечание: Это реализация IEEE754 , реализация double может отличаться в других стандартах языка)

An unsigned int (он же size_t) использует все 64-битные числа для хранения числа, но для экспонент не осталось пробелов и, следовательно, нет точности с плавающей запятой в целых числах, таких как size_t

Следовательно, компилятор говорит вам, что если ваше 64-битное целое число без знака больше, чем то, что может хранить мантисса 64-битного double -типа (т. е. больше , чем 52 бита ), это может привести к потере данных и, возможно, к неопределенному поведению в остальной части кода впоследствии.

Выполнение static_cast<double>(idx) - это утверждение программиста, говорящее компилятору не беспокоиться и которое вы будете держать в соблюдайте вышеуказанные меры предосторожности.

Источник: https://en.wikipedia.org/wiki/Double-precision_floating-point_format

0 голосов
/ 06 февраля 2020

Это предупреждение, потому что программист может не понимать, что они теряют биты во время присваивания.

Но если у вас есть явное приведение, компилятор предполагает, что программист знает, что он делает, потому что приведение прямо там и очень в вашем лице.

...