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

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

5 часов назад, kolobok0 сказал:

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

Разделите. Калькулятор по почте прислать?

Для справки: 65536 - это степени 2, а 0,1, 10, 100 - это степени 10. И 65536/10 = 6553,6. И даже если отбросить дробную часть, введя погрешность, то 6553 не является степенью 2.

Изменено пользователем EdgeAligned

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


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

15 часов назад, Forger сказал:

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

Открою Вам страшную тайну: "Обычная целочисленная арифметика" в процессоре - тоже двоичная; и умножение в ней - тоже комбинация сдвигов и сложений.

Только никому не рассказывайте! Ведь это - тайна!

:biggrin:

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


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

21 minutes ago, jcxz said:

Открою Вам страшную тайну:

Вы прекрасно поняли о чем шла речь, но видимо перевесила потребность по-умничать 💪

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


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

Как я писал выше, если перейти с системы счисления с основанием степени 10 на систему с основанием степени 2, получим тот эффект, когда в килобайте 1024 байта. И это будет непривычно для нашего "человеческого" мира. Но если готовы мириться с таким "неровным" счетом, то пожалста 🙂 

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


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

18 минут назад, EdgeAligned сказал:

Как я писал выше, если перейти с системы счисления с основанием степени 10 на систему с основанием степени 2, получим тот эффект, когда в килобайте 1024 байта. И это будет непривычно для нашего "человеческого" мира. Но если готовы мириться с таким "неровным" счетом, то пожалста 🙂 

Не очень понятно - причём тут "системы счисления"? kolobok0 вроде писал про положение точки, разделяющей целую и дробную часть числа (в fixed point числах), а не про систему счисления.

Как именно задавать положение этой самой точки: в десятичных или двоичных разрядах - вопрос спорный. Как это делать оптимальнее - будет зависеть от того, для каких операций используются эти числа. О чём ТС не сказал ни слова. Если гадать на кофейной гуще и исходному сообщению ТС, то используется это для некоего "коэффициента". Видимо для каких-то расчётов. А если для расчётов, то возможно там есть и расчёты в плавучке. А значит - оптимальнее будет использовать смещение точки в степенях двойки, а не 10. Так как преобразование из fixed point в плавающую точку и обратно в этом случае будет выполняться и быстрее и не будет вносить дополнительную погрешность (так как и во float и в double положение точки - тоже задаётся в двоичных разрядах). Если же смещать в десятичных разрядах, то при каждом преобразовании будет добавляться ошибка преобразования.

А системе команд ARM в операциях преобразования int->float и обратно, даже в саму команду заложена возможность опционального сдвига на 2^n. Т.е. - операция сдвига вообще не требует  ни одного такта.

Например я почти всегда использую fixed point с положением точки, заданным в двоичных разрядах. Так как это оптимальнее по вычислениям и точности.

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


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

Как именно задавать положение этой самой точки: в десятичных или двоичных разрядах - вопрос спорный.
Ну, справедливости ради, десятичные разряды можно выделить лишь в BCD-представлении, n'est-ce pas?

PS: а вообще, мы стали свидетелями - очередное поколение обнаруживает невозможность точного представления десятичных дробей в двоичной арифметике (((-8Ж
Изменено пользователем Obam

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


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

9 часов назад, Obam сказал:

Ну, справедливости ради, десятичные разряды можно выделить лишь в BCD-представлении, n'est-ce pas?

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

Цитата

PS: а вообще, мы стали свидетелями - очередное поколение обнаруживает невозможность точного представления десятичных дробей в двоичной арифметике (((-8Ж

Не стали - эти недоумения возникали во всех поколениях. Лично знаю людей, которые десятки лет программировали на Си, и тут такое "открытие". Бывает и такое.

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


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

Положение точки можно отмерять хоть в метро-попугаях. Надо только условиться, как хранить, и смириться с последствиями ошибок округления, ведь процессор продолжает работать с двоичными числами.
Посреди тетрады предлагаю (((-8Ж
ШУТКА!!!

мы стали свидетелями - очередное поколение обнаруживает невозможность
Не стали - эти недоумения возникали во всех поколениях.
Как же не стали? (((-8Ж Прям на глазах очередное присоединилось к предшествующим (((-8Ж
Изменено пользователем Obam

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


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

В 13.01.2024 в 18:23, 1113 сказал:

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

ну  сначала умножил на 10 , перевёл в int, потом прибавил 1 перевёл во float, и разделил на 10 

В 13.01.2024 в 18:47, Forger сказал:

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

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

там потом надо результаты суммирования делить друг на друга условно 458,6 разделить на 385,3  и если делить  4586  на 3853 , то не получится нормальный результат. Пока что делаю так  сначала умножил на 10 , перевёл в int, потом прибавил 1 перевёл во float, и разделил на 10 

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


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

56 минут назад, RR2021 сказал:

Пока что делаю так  сначала умножил на 10 , перевёл в int, потом прибавил 1 перевёл во float, и разделил на 10 

Мои глаза!!! 

Что это изменит? Значение 1.1 во float не представимо точно.

image.png.ca63230473357b6b41c8fe94908ef67e.png

 

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


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

8 минут назад, VladislavS сказал:

 

Что это изменит? 

т.к. я в цикле прибавляю 0,1 , то по крайней мере ошибка не накапливается и не увеличивается 

 

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


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

Какая разница, будет у вас там 2e-8 или 1e-3 ошибка, если вы на всё что меньше 0.1 в итоге чихаете?

 

PS: Как писали раньше, принимаем младший разряд int за 0.1 и работаем в целых числах.

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


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

2 часа назад, RR2021 сказал:

ну  сначала умножил на 10 , перевёл в int, потом прибавил 1 перевёл во float, и разделил на 10 

...и таким образом - дважды прибавил ошибку преобразования.  :dash2:

2 часа назад, RR2021 сказал:

там потом надо результаты суммирования делить друг на друга условно 458,6 разделить на 385,3  и если делить  4586  на 3853 , то не получится нормальный результат. Пока что делаю так  сначала умножил на 10 , перевёл в int, потом прибавил 1 перевёл во float, и разделил на 10 

:shok: На кой???

На кой это надевание трусов через голову?

У вас процессор - с FPU или нет? Если с FPU, то почему просто не делать всё во float?

 

Если процессор без FPU, то почему не сдвинуть точку в любую удобную для вычислений позицию 2^n (как советовал выше kolobok0), и не проводить все вычисления в fixed point?

Ведь элементарно же все операции можно в fixed point сделать:

u32 x = (u32)(458.5 * (1u << 22));      //формат: uq10.22
u32 y = (u32)(385.3 * (1u << 22));      //формат: uq10.22
...
x += (u32)(0.1 * (1u << 22));           //формат: uq10.22
...
u32 result = (u32)(((u64)x << 22) / y); //формат: uq10.22

Здесь у x, y и result точка находится в позиции 1<<22. Но можно выбрать и любую другую, удобную для вычислений позицию точки. Кроме того - в разных местах кода позиция точки может быть разной. Оптимальная позиция точки выбирается исходя из диапазона значений аргументов, диапазона промежуточных и конечных результатов и требуемой точности вычислений.

Математика начальных классов школы.

 

PS: Именно отсюда видно - почему во многих случаях оптимальнее позицию точки держать в двоичных разрядах, а не в десятичных. О чём я писал выше. И от чего у некоторых персонажей так подгорало.  :biggrin:

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


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

25 минут назад, VladislavS сказал:

Какая разница, будет у вас там 2e-8 или 1e-3 ошибка, если вы на всё что меньше 0.1 в итоге чихаете?

 

PS: Как писали раньше, принимаем младший разряд int за 0.1 и работаем в целых числах.

полученные значение не конечный результат. на него потом делится другое число и ещё одно, складываются, делятся друг на друга .

по итогу написав для сравнения два куска кода где переводится в int и где всё во float , разница получилась очень существенная , то значение  где с переводом в int, при пересчёте на калькуляторе оказалась правильным

14 минут назад, jcxz сказал:

 

Математика начальных классов школы.

 

не всем повезло учится в школах, где в начальных классах преподают разные системы счисления,  и то как в двоичном коде представляются float, то что вам повезло очень за вас рад. а у меня всё по простому было 

Изменено пользователем RR2021

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


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

2 hours ago, RR2021 said:

там потом надо результаты суммирования делить друг на друга условно 458,6 разделить на 385,3  и если делить  4586  на 3853 , то не получится нормальный результат.

ну, коли дальше идет работа с дробью, то ухожу во float на время расчетов

но исходные данные, особенно инкременты/декременты предпочитаю хранить в целых числах, т.е. "убрать из уравнения" хотя бы источник накопления ошибки )

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


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

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

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

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

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

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

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

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

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

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