Перейти к содержанию
    

Почему 1 + 0.1 = 1.0000002 ??? и что с этим делать?

в общем вот выделил вот кусочек кода где коэффициенту приравнивается 1  прибавляется  0.1 и получается 1.0000002 

почему это происходит 

а главное что с этим делать ну если например надо циклически увеличивать коэффициент на 0.1 там со временем прилично набегает и расчёты кривые получаются 

код1.jpg

код2.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, RR2021 said:

почему это происходит

потому что способ кодирования float не позволяет получить строго константу 0.1

12 minutes ago, RR2021 said:

что с этим делать

float это двоичная кодировка, переводите расчет с десятичной на двоичную математику. ну или увеличивайте точность переменных

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 minutes ago, RR2021 said:

что с этим делать ну если например надо циклически увеличивать коэффициент на 0.1 там со временем прилично набегает и расчёты кривые получаются

Делаете циклическое увеличение целочисленного значения и на каждой итерации пересчитываете своё дробное значение из него.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если важно точное значение, то умножьте оба числа на 10 (мысленно) и запишите int k_L = 10; k_L += 1; , а потом по месту применения в формуле поделите на 10.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

44 minutes ago, RR2021 said:

всем спасибо! если записывать  в int  всё работает 

и как вам удалось записать в int 0.1?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 минут назад, 1113 сказал:

и как вам удалось записать в int 0.1?

Записать-то можно, вот что при считывании будет))))))))))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 minutes ago, 1113 said:

и как вам удалось записать в int 0.1?

если инкремент всегда кратен 0.1 и бОльшая точность не требуется, то проще перейти в целые числа и в таком виде хранить данные (х10).

Т.е. инкремент на 0.1 будет значить +1, без всякой дробной части. Для удобства саму переменную можно назвать так, чтобы это отражалось в сути хранения в ней данных. Да, костыль, но вполне рабочий. Главное просто потом не запутаться )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 1/13/2024 at 5:04 PM, 1113 said:

потому что способ кодирования float не позволяет получить строго константу 0.1

Ну, не до такой же степени, что 0.1 превращается в 0.0000002.

On 1/13/2024 at 4:54 PM, RR2021 said:

в общем вот выделил вот кусочек кода где коэффициенту приравнивается 1  прибавляется  0.1 и получается 1.0000002 

почему это происходит 

а главное что с этим делать ну если например надо циклически увеличивать коэффициент на 0.1 там со временем прилично набегает и расчёты кривые получаются 

Вы пишите одно, а в картинках приводите другое.

У вас в отладчике не 1.0000002, а 1.1000002.

И причем картинки, которые вы привели очень плохо читаются. Результаты вычисления очень тяжело разглядеть.

Судя по отладчику, ваш k_L это float, а числа, которые вы присваиваете и прибавляете к k_L являются типом double !!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, RR2021 said:

приравнивается 1  прибавляется  0.1 и получается 1.0000002

Числа записаны не правильно. Прочитайте о том, как в С записываются числа с плавающей точкой и почему их надо записывать не так как у вас. Нет, их можно записывать так как на скриншоте, но тогда возникает вопрос, указанный в теме.

Подсказка: обратите внимание, что в дизассемблере присутствует вызов преобразования float в double.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 1/13/2024 at 5:28 PM, EdgeAligned said:

Если важно точное значение, то умножьте оба числа на 10 (мысленно) и запишите int k_L = 10; k_L += 1; , а потом по месту применения в формуле поделите на 10.

 

23 hours ago, Forger said:

если инкремент всегда кратен 0.1 и бОльшая точность не требуется, то проще перейти в целые числа и в таком виде хранить данные (х10).

Т.е. инкремент на 0.1 будет значить +1, без всякой дробной части. Для удобства саму переменную можно назвать так, чтобы это отражалось в сути хранения в ней данных. Да, костыль, но вполне рабочий. Главное просто потом не запутаться )

 

Если идёт речь про МК, то лучше умножать на 65536. А у результата тупо откидывать младшее слово. Ну или делить на 65536. Так точнее будет и/или быстрее. Можно (если есть промежуточные сомножители-коэффициенты) сразу их выразить через данный числитель.

 

 

(круглый)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, kolobok0 said:

Если идёт речь про МК, то лучше умножать на 65536.

а почему не 32768? Почему не 16384 и т.д.

Я частенько применяю такой принцип - хранение в целых числах. Это и работает гораздо быстрее и нет подобных ошибок.

Но стараюсь использовать величины кратные "трем нулям": 1/1000, 1/1000000 .... делая соотв. приписки к имени переменной: valueXXX_ms, timeXXX_ns и т.п.

А заморачиваться как вы предлагаете с арифметикой умножения/деления на сдвигах (степени двойки) - для этого нужны наверно уж ооооочень веские причины и камень и код должны быть крайне убогими, раз приходится идти на такие отчаянные шаги )

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, kolobok0 сказал:

то лучше умножать на 65536

Хорошо, умножим. А сколько будет шаг приращения 0,1 * 65536?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, EdgeAligned said:

Хорошо, умножим. А сколько будет шаг приращения 0,1 * 65536?

0,1 - называется "одна десятая" - т.е. одна часть из десяти, т.е. разделите на десять.

3 hours ago, Forger said:

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

3 hours ago, Forger said:

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

33 minutes ago, kolobok0 said:

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

да, если это не влияет положительно на выгоду от продаж, а влияет лишь на личное эго кодера, его потребность выпендрится на ровном месте, создать "непреодолимую" проблему на ровном месте и ее победоносно решать

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

у вас были проекты с много-много-тысячными партиями изделий?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...