Форум программистов, компьютерный форум, киберфорум
C (Си)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.56/16: Рейтинг темы: голосов - 16, средняя оценка - 4.56
1 / 1 / 1
Регистрация: 30.06.2021
Сообщений: 31

Где теряется точность?

04.09.2022, 20:40. Показов 3592. Ответов 23

Студворк — интернет-сервис помощи студентам
Здравствуйте, сразу к делу:

C
1
2
3
4
5
6
7
8
9
10
11
12
double x;
double z;
printf("Input x: ");
scanf("%lf",&x);
if(x<=0){
        z=0;
    }else if(x<0||x<=1){
        z=pow(x,2)-x;
    }else{
        z=pow(x,2)-(sin(M_PI*pow(x,2)));
    }
printf("If x=%lf, then z=%lf\n",x,z);
Вводим x=7 и получаем ответ: z=49.0000

А если написать так:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double x;
double z;
float y;
printf("Input x: ");
scanf("%lf",&x);
y=M_PI*pow(x,2);
if(x<=0){
        z=0;
    }else if(x<0||x<=1){
        z=pow(x,2)-x;
    }else{
        z=pow(x,2)-(sin(y));
    }
printf("If x=%lf, then z=%lf\n",x,z);
Вводим x=7 и получаем ответ: z=48.999994
причём, если 'y' сделать double, опять получаем округление до 49.0000
Где теряется точность?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.09.2022, 20:40
Ответы с готовыми решениями:

Теряется точность
Видимо в этой проге теряетмя точность. Не проходит только 1 тест. #include &lt;iostream&gt; #include &lt;iomanip&gt; using...

Куда теряется точность?
Для примера, есть формула (a+b)3 - a3. В расчетах с хранением промежуточных результатов и без него получаются разные ответы. #include...

Теряется точность в сравнении с exel
Точность измерений на С++ меньше чем на exel. Нужно это исправить. Код проги #include &lt;iostream&gt; #include &lt;cmath&gt; ...

23
599 / 421 / 137
Регистрация: 02.10.2008
Сообщений: 1,798
Записей в блоге: 1
08.09.2022, 10:51
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от мама Стифлера Посмотреть сообщение
Или его процессор, получается вычисляет более точно.
Проц - это вряд ли.
Много зависит от реализации printf()
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,980
08.09.2022, 14:48
Цитата Сообщение от drfaust Посмотреть сообщение
Много зависит от реализации printf()
мама Стифлера, ну да, скорее всего. У меня на довольно древнем компе с более другой (как любит говорить один форумчанин) ОС и gcc, и clang выдают ровно такой же результат, какой получился на относительно новом компе с вин 10 и компилятором cl от последней студии.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
[andrew@srv /usr/home/andrew/prog/c/num]$ gcc -Wall 0501.c 
[andrew@srv /usr/home/andrew/prog/c/num]$ ./a.out 
a = 0.50000000000000000000
b = 0.10000000000000000555
c = 0.50000000000000000000
d = 0.10000000149011611938
[andrew@srv /usr/home/andrew/prog/c/num]$ uname -sr
FreeBSD 13.0-RELEASE-p11
[andrew@srv /usr/home/andrew/prog/c/num]$ sysctl hw.model
hw.model: Pentium(R) Dual-Core  CPU      E5500  @ 2.80GHz
[andrew@srv /usr/home/andrew/prog/c/num]$ gcc -dumpversion
11.3.0
[andrew@srv /usr/home/andrew/prog/c/num]$
Видимо, разработчики вашего
Цитата Сообщение от мама Стифлера Посмотреть сообщение
TDM-GCC
посчитали, что 17 знаков после запятой "за глаза" всем хватит...
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
09.09.2022, 20:38
Вспомнил про эту тему, вот мои результаты (gcc/linux, Float, Double, Long double):
Адрес байтов растет влево.
Code
1
2
3
4
5
6
7
8
// для присваивания 0.5
f: 3f 00 00 00
d: 3f e0 00 00 00 00 00 00
l: 00 00 55 cf 53 0b 3f fe 80 00 00 00 00 00 00 00
// для присваивания 0.1 (присваивание для long double требует константы правильного типа, 0.1 не прокатит)
f: 3d cc cc cd
d: 3f b9 99 99 99 99 99 9a
l: 00 00 55 84 d9 19 3f fb cc cc cc cc cc cc cc cd
99 и cc соответствуют повтору битов 1100, представляющих бесконечную двоичную дробь для числа 0.6 представленного в мантиссе согласно представлению IEEE. (1.6B-4, единица не хранится).
0.6 в двоичном это 0.(1001). В зависимости от границы байта это может быть 0х33, 0х66, 0х99 или 0xcc

Во всех случаях выше округление правильно выполняется вверх, поэтому погрешность для 0.1 тоже вверх.
Погрешность для представления 0.1 равна значению нижнего бита мантиссы, минус отброшенный остаток.
Float мантисса 23 бита, -100 1100 1101, значение нижнего бита 2-23, экспонента 2-4, т.е. 2-27.
Величина отброшенного хвоста 1100 1100... начиная с 24 бита это 1.6*2-24, и экспонента 2-4, всего 1.6*2-28.

Разница между двумя: 0.4*2-28, или 0.000000001490116119384765625, десятичная дробь конечной длины.
Если написать printf() очень аккуратно, то printf( "%.30f", (float)0.1 ) должен вывести 0.100000001490116119384765625000.

У меня ровно столько и выводит.

Если кому-то интересно поиграться, код ниже.

Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
 
#define DUMP(x) for( int i = (printf( "%s: ", #x ), sizeof( x )) ; i-- ; ) \
                    printf( i ? "%02x " : "%02x\n", ((const unsigned char*)&(x))[i] )
 
int main()
{
  float  f = 0.1;
  double d = 0.1;
  long double l = 0.1l;
 
  DUMP( f );
  DUMP( d );
  DUMP( l );
 
  printf( "0.000000001490116119384765625--\n%.30f\n", (float)0.1 );
 
  return 0;
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,312
10.09.2022, 20:00
Лучший ответ Сообщение было отмечено Zicrys как решение

Решение

Цитата Сообщение от Zicrys Посмотреть сообщение
Где теряется точность?
Потеря точности при таком изменении кода происходит/может происходить как минимум под двум причинам:

1. Использование float в качестве промежуточного типа, в то время как с точки зрения языка все выражение вычисляется в типе double. Это приводит к "огрублению" промежуточного результата. Об этом вам уже рассказали.

2. Сам факт выноса подвыражения M_PI*pow(x,2) из целого выражения pow(x,2)-sin(M_PI*pow(x,2)), даже (!) если бы промежуточный результат сохранялся в типе double, то есть даже если бы с тривиальной точки зрения потери точности "не могло быть".

Реализация может использовать модель плавающих вычислений, которая выполняет все промежуточные вычисления в рамках полного выражения в супервысокой точности, т.е. в точности, превышающей точность типа double. Всякий раз, когда вы подразбиваете плавающее выражение на подвыражения с записью в промежуточные переменные, это приводит к огрублению промежуточных результатов.

Будет ли иметь место этот эффект зависит от используемой реализацией модели плавающих вычислений. Мы все прекрасно помним это явление, когда плавающие вычисления на платформе x86 выполнялись средствами FPU. С переходом на использование SSE2 это явление становится менее актуальным.

Другими словами, даже при использовании "правильных" типов

C
1
2
3
4
double a, b, c, d;
...
double x = a * b + c / d;
double y1 = a * b, y2 = c / d, y = y1 + y2;
финальные значения (x и y в примере) могут быть разными (см. FP_CONTRACT).
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.09.2022, 20:00

Теряется точность переменной типа double
Вот код: double StepC = 0.001, g_C; for ( double c = StepC; c &lt;= 3; c += StepC ) { //...

Теряется точность при вычислении с double
Доброго времени суток. В процессе решения кубического уравнения, у меня теряется точность переменной типа double. Пробовал использовать...

Умножение преобразованием Фурье. Теряется точность
Добрый день ребятки. У кого есть какие мысли? Поделитесь. Само преобразование Фурье: #define K2PI...

Где то теряется post
Всем привет. Есть форма: &lt;form method=&quot;post&quot; action=&quot;http://localhost/wp-login.php&quot; id=&quot;loginform&quot; name=&quot;loginform&quot;&gt; &lt;p&gt; ...

Где теряется кодировка ?
Непонятная проблемка внутри процедуры путь программы в нормальном виде , при передаче в другую процедуру уже кракозябры . где копать ? ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
24
Ответ Создать тему
Новые блоги и статьи
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний против массовых профанаций
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
SUNO Ai - Река Без Дна
zorxor 31.07.2026
Автор стихотворения - астрофизик Марина Катыс Ссылка на сгенерированную музыкальную композицию: https:/ / suno. com/ song/ 6f6e5464-b290-4650-be6c-44c85f8d8013 Я говорю, что Время- как вода течет. . .
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru