Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Потеря точности???? / 25 сообщений из 46, страница 1 из 2
12.10.2006, 11:29
    #34049631
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
есть код:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
double x= 0 . 000000001 ,z1;
unsigned long y= 1000000000 ,z2;

z1=x*y;
z2=x*y;
cout<<"x:"<<x<<"\ny:"<<y<<"\n";
cout<<"z1=x*y:"<<z1<<"\nz2=x*y:"<<z2<<"\n";
x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
z2=x*y;
cout<<"x:"<<x<<"\ny:"<<y<<"\n";
cout<<"z1=x*y:"<<z1<<"\nz2=x*y:"<<z2<<"\n";


получим следующие результаты:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
x:1e- 09 
y: 1000000000 
z1=x*y: 1 
z2=x*y: 1 
x: 1 .6e- 06 
y: 625000 
z1=x*y: 1 
z2=x*y: 0 
Явно что во втором случае z2=0 не правильно, но не пойму почему так и почему в первом случае (x и у - степень десяти) все работает как надо...
Any ideas?
...
Рейтинг: 0 / 0
12.10.2006, 12:01
    #34049826
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Здесть нет потери точности, потому как double в принциве неточный тип данных. Ты выведи double в полном формате, чтобы не одна десятичная цифра была, а больше, и увидешь все, что происходит. Так что здесь все правильно.
...
Рейтинг: 0 / 0
12.10.2006, 12:16
    #34049920
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
MasterZivЗдесть нет потери точности, потому как double в принциве неточный тип данных. Ты выведи double в полном формате, чтобы не одна десятичная цифра была, а больше, и увидешь все, что происходит. Так что здесь все правильно.

Да неее... тут че-то другое.
1. cout.precision(10) все равно выводит те же числа.
2. если делаем так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
double x,z1;
unsigned long y,z2;

double temp;

x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
temp=x*y;
z2=temp;
cout<<"x:"<<x<<"\ny:"<<y<<"\n";
cout<<"z1=x*y:"<<z1<<"\nz2=x*y:"<<z2<<"\n";
то все работает и мы получаем 1 как для z1 так и для z2!
Т.е. какого-то она странным образом округляет/отбрасывает че-то в случае если тип результирующей переменной unsigned long.
...
Рейтинг: 0 / 0
12.10.2006, 12:31
    #34050014
a_shar
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
В VC 6 все нормально выводит.

x:1e-009
y:1000000000
z1=x*y:1
z2=x*y:1
x:1.6e-006
y:625000
z1=x*y:1
z2=x*y:1
...
Рейтинг: 0 / 0
12.10.2006, 12:41
    #34050071
man_555
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
bemtaill какой компилятор?
...
Рейтинг: 0 / 0
12.10.2006, 12:46
    #34050118
man_555
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.
...
Рейтинг: 0 / 0
12.10.2006, 12:49
    #34050138
Карабас Барабас
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
man_555
m> т.к. результат должен быть unsigned, компилятор x приводит
m> к unsigned (в резульатае 0), а затем перемножает. Таким
m> образом получаем 0 в результатеЕсли мне не изменяет память, то по стандарту два операнда приводятся к максимальному типу, а к типу результата уже приводится результат операции
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
12.10.2006, 12:56
    #34050186
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Карабас Барабас man_555
m> т.к. результат должен быть unsigned, компилятор x приводит
m> к unsigned (в резульатае 0), а затем перемножает. Таким
m> образом получаем 0 в результатеЕсли мне не изменяет память, то по стандарту два операнда приводятся к максимальному типу, а к типу результата уже приводится результат операции
Posted via ActualForum NNTP Server 1.3

да, помоему так и есть....

компилятор:
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-56)
...
Рейтинг: 0 / 0
12.10.2006, 12:59
    #34050210
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
man_555imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.

Хотя это единственное логичное объяснение
...
Рейтинг: 0 / 0
12.10.2006, 13:05
    #34050254
LeonM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
В "древних" компиляторах операнды сперва приводились к типу первого из них. Сравните x*y и y*x.
...
Рейтинг: 0 / 0
12.10.2006, 13:06
    #34050261
Akh
Akh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
bemtaill man_555imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.

Хотя это единственное логичное объяснение

Сделай как сказал MasterZiv для двух вариантов. В первом будет 1.000000000, а во втором 0,99999999999
...
Рейтинг: 0 / 0
12.10.2006, 13:10
    #34050289
man_555
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
bemtaill man_555imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.

Хотя это единственное логичное объяснение

а ради эксперимента попробуй
z1=y/x;
z1=x*(double)y;

Интересно, что получится?

Про стандарт: не помню, поэтому буду благодарен, если ткнёте носом в нужный абзац.
...
Рейтинг: 0 / 0
12.10.2006, 13:14
    #34050305
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Akh bemtaill man_555imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.

Хотя это единственное логичное объяснение

Сделай как сказал MasterZiv для двух вариантов. В первом будет 1.000000000, а во втором 0,99999999999

Подожди, не понял:)
MasterZiv сказал:
"Ты выведи double в полном формате, чтобы не одна десятичная цифра была, а больше, и увидешь все, что происходит. Так что здесь все правильно."
Ну я и вывожу по десять знаков после запятой. Для обоих вариантов.
+
почему тогда в таком случае работает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
double x,z1;
unsigned long y,z2;

double temp;

x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
temp=x*y;
z2=temp;
cout<<"x:"<<x<<"\ny:"<<y<<"\n";
cout<<"z1=x*y:"<<z1<<"\nz2=x*y:"<<z2<<"\n";
ведь согласно твоему предположению temp=0,99999999 (хотя реально он равен 1) и при присваивании z2=temp ничего не теряется...

Такое ощущение что компилятор глючит...
...
Рейтинг: 0 / 0
12.10.2006, 13:16
    #34050315
man_555
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
LeonMВ "древних" компиляторах операнды сперва приводились к типу первого из них. Сравните x*y и y*x.

компилятор не глючит ;-)
...
Рейтинг: 0 / 0
12.10.2006, 13:16
    #34050318
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
man_555 bemtaill man_555imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.

Хотя это единственное логичное объяснение

а ради эксперимента попробуй
z1=y/x;
z1=x*(double)y;

Интересно, что получится?

Про стандарт: не помню, поэтому буду благодарен, если ткнёте носом в нужный абзац.

Ща попробую...
...
Рейтинг: 0 / 0
12.10.2006, 13:25
    #34050360
Akh
Akh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
bemtaillведь согласно твоему предположению temp=0,99999999 (хотя реально он равен 1) и при присваивании z2=temp ничего не теряется...

Такое ощущение что компилятор глючит...

Ты уверен, что при выводе в stdout дубль не округляется?
...
Рейтинг: 0 / 0
12.10.2006, 13:28
    #34050376
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Akh bemtaillведь согласно твоему предположению temp=0,99999999 (хотя реально он равен 1) и при присваивании z2=temp ничего не теряется...

Такое ощущение что компилятор глючит...

Ты уверен, что при выводе в stdout дубль не округляется?

Еще больше не понял:)

Это че получается, говоришь вывести дубль а выводит автоматом инт???
ща тогда в дебагере посмотрю...
...
Рейтинг: 0 / 0
12.10.2006, 13:31
    #34050391
Akh
Akh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
bemtaillща тогда в дебагере посмотрю...

Вот отсюда и стоит разбиратья
...
Рейтинг: 0 / 0
12.10.2006, 13:35
    #34050415
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
man_555 bemtaill man_555imho происходит это потому, что
y - unsigned
z2 - unsigned

т.к. результат должен быть unsigned, компилятор x приводит к unsigned (в резульатае 0), а затем перемножает. Таким образом получаем 0 в результате.

Хотя это единственное логичное объяснение

а ради эксперимента попробуй
z1=y/x;
z1=x*(double)y;

Интересно, что получится?

Про стандарт: не помню, поэтому буду благодарен, если ткнёте носом в нужный абзац.


Прикольно:
Код: plaintext
1.
2.
3.
4.
5.
z1=y/x: 390625000000 
z1=x*(double)y: 1 
 
z2=y/x: 4077943360 
z2=x*(double)y: 0 

z1 - double
z2 - unsigned int

очевидно переполнение UInt
...
Рейтинг: 0 / 0
12.10.2006, 13:40
    #34050431
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Akh bemtaillща тогда в дебагере посмотрю...

Вот отсюда и стоит разбиратья

короче ни че ни где не округлетя - все как на экране так и в дебагере!
...
Рейтинг: 0 / 0
12.10.2006, 13:41
    #34050443
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Лана надо работать, а то уже 2 часа на эту хрень убил:)) если у кого какие мысле появятся - пишите, буду рад!
...
Рейтинг: 0 / 0
12.10.2006, 13:44
    #34050455
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Лана надо работать, а то уже 2 часа на эту хрень убил:)) если у кого какие мысле появятся - пишите, буду рад!
...
Рейтинг: 0 / 0
12.10.2006, 13:56
    #34050497
Barlone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Хотите объясню, откуда разница между этим
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
double x,z1;
unsigned long y,z2;
double temp;
x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
temp=x*y;
z2=temp;
и этим
Код: plaintext
1.
2.
3.
4.
5.
6.
double x,z1;
unsigned long y,z2;
x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
z2=x*y;
По-хорошему, надо на генерируемый код смотреть, но так навскидку...
Вы же на x86 тестируете, да :) ?
Компилятор приводит x и y к double (естественно), перемножает, в результате получается что-то типа 0.9(9 в периоде). В регистре сопроцессора - то есть десятибайтный тип. Теперь если сразу приводить к long, компилятор делает это прямо из этого регистра сопроцесссора, а там целая часть 0. А если сначала сохранить в переменную double - а это восьмибайтный тип - то произойдет округление к ближайшему числу представимому в double, а это как раз 1. С msvc результаты одинаковые, так как он устанавливает для сопроцессора режим вычислений с восьмибайтной точностью.
...
Рейтинг: 0 / 0
12.10.2006, 13:58
    #34050504
Barlone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
Кстати если заменить double temp на long double temp (а это десятибайтный тип в gcc и bcc) то снова будет 0.
...
Рейтинг: 0 / 0
12.10.2006, 14:03
    #34050522
bemtaill
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Потеря точности????
BarloneХотите объясню, откуда разница между этим
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
double x,z1;
unsigned long y,z2;
double temp;
x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
temp=x*y;
z2=temp;
и этим
Код: plaintext
1.
2.
3.
4.
5.
6.
double x,z1;
unsigned long y,z2;
x= 0 . 0000016 ;
y= 625000 ;
z1=x*y;
z2=x*y;
По-хорошему, надо на генерируемый код смотреть, но так навскидку...
Вы же на x86 тестируете, да :) ?
Компилятор приводит x и y к double (естественно), перемножает, в результате получается что-то типа 0.9(9 в периоде). В регистре сопроцессора - то есть десятибайтный тип. Теперь если сразу приводить к long, компилятор делает это прямо из этого регистра сопроцесссора, а там целая часть 0. А если сначала сохранить в переменную double - а это восьмибайтный тип - то произойдет округление к ближайшему числу представимому в double, а это как раз 1. С msvc результаты одинаковые, так как он устанавливает для сопроцессора режим вычислений с восьмибайтной точностью.

Действительно!!! Спасибо.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Потеря точности???? / 25 сообщений из 46, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]