Откриване на загуба на точност при преобразуване от двойно към плаващо

Пиша част от кода, в който трябва да конвертирам от двойни към плаващи стойности. Използвам boost::numeric_cast, за да направя това преобразуване, което ще ме предупреди за всяко препълване/недостатъчно препълване. Въпреки това ми е интересно да разбера дали това преобразуване е довело до някаква загуба на точност или не.

Например

    double source =  1988.1012;
    float dest = numeric_cast<float>(source);

Произвежда dest със стойност 1988.1

Има ли някакъв наличен начин, по който мога да открия този вид загуба/закръгляване на точност


person Yogesh Arora    schedule 13.07.2010    source източник
comment
В този случай винаги ще има загуба на точност.   -  person Paul R    schedule 13.07.2010


Отговори (4)


Можете да хвърлите плувката обратно към дубъл и да сравните този дубъл с оригинала - това трябва да ви даде точна индикация дали има загуба на прецизност.

person Will A    schedule 13.07.2010
comment
По-добре от справедливо. Той ще ви каже точно дали е изгубена някаква информация. - person Stephen Canon; 13.07.2010

float dest = numeric_cast<float>(source);
double residual = source - numeric_cast<double>(dest);

Следователно residual съдържа „загубата“, която търсите.

person Jacob    schedule 13.07.2010

Вижте тези статии за единична точност и плаващи с двойна точност. На първо място, плаващите имат 8 бита за експонента срещу 11 за двойно. Така че всичко, което е по-голямо от 10^127 или по-малко от 10^-126 по величина, ще бъде преливането, както споменахте. За float имате 23 бита за действителните цифри на числото, срещу 52 бита за двойното. Така че очевидно имате много повече цифри на точност за двойното, отколкото за плаващото.

Кажете, че имате число като: 1,1123. Това число всъщност може да не е кодирано като 1.1123, тъй като цифрите в числото с плаваща запетая се използват за действително събиране като дроби. Например, ако вашите битове в мантисата са 11001, тогава стойността ще бъде формирана от 1 (неявно) + 1 * 1/2 + 1 * 1/4 + 0 * 1/8 + 0 * 1/16 + 1 * 1/32 + 0 * (64 + 128 + ...). Така че точната стойност не може да бъде кодирана, освен ако не можете да съберете тези дроби по такъв начин, че да е точното число. Това е рядкост. Следователно почти винаги ще има загуба на точност.

person Dave    schedule 13.07.2010
comment
Мога ли да предложа да посочите често споменатия docs.sun.com/source/806- 3568/ncg_goldberg.html вместо това? (Нямам достатъчно представител, за да го направя сам) - person Alexandre C.; 13.07.2010

Ще имате определено ниво на загуба на точност, според отговора на Дейв. Ако обаче искате да се съсредоточите върху количественото му определяне и предизвикване на изключение, когато то надвиши определено число, ще трябва да отворите самото число с плаваща запетая и да анализирате мантисата и експонентата, след което да направите анализ, за ​​да определите дали надхвърлих твоя толеранс.

Но добрата новина е, че това е обикновено стандартният IEEE float с плаваща запетая. :-)

person Paul Nathan    schedule 13.07.2010