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

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

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

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

Здесь не нужно знание систем счисления. Достаточно только владеть 4-мя базовыми арифметическими операциями. В моём коде выше ничего кроме них и не используется.

А "двоичное представление float" - это вообще к чему? :wacko2:  И какое оно имеет отношение к вычислениям выше?

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


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

5 минут назад, Forger сказал:

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

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

ну пока что я тоже к такому методу пришёл, совета лучше пока не увидел 

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


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

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

ну пока что я тоже к такому методу пришёл, совета лучше пока не увидел 

Да уж совет просто "супер". Особенно для CPU без FPU.  :biggrin:

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


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

7 minutes ago, RR2021 said:

совета лучше пока не увидел 

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

 

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


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

29 минут назад, Forger сказал:

и бессмысленной "гуру"-оптимизации на абсолютно ровном месте ))

Да уж... ведь "миллион мух не могут ошибаться". Если они куда-то летят, то видимо там что-то вкусное лежит.  :biggrin:

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


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

5 minutes ago, jcxz said:

"миллион мух не могут ошибаться"

А вот и "традиционное" хамство, ожидаемо.

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


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

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

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

: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:

 (458.5 + 0.1) / 385.3 =   1,190241370360758

Берём ваш код  

uint32_t x = (uint32_t)(458.5 * (1u << 22));      //формат: uq10.22

uint32_t y = (uint32_t)(385.3 * (1u << 22));      //формат: uq10.22

 

x += (uint32_t)(0.1 * (1u << 22));  

 

uint32_t result = (uint32_t)(((uint64_t)x << 22) / y);

result равен  0x004C2CEA

первые 10 бит  дают 1

а оставшиеся 22 это 0b 00 1100 0010 1100 1110 1010  или 0хC2CEA или в десятичной 797 930 и как это интерпретировать или представить в виде   0,190241370360758 ну т.е. то что после точки ?

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

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


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

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

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

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

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


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

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

uint32_t result = (uint32_t)(((uint64_t)x << 22) / y);

 

result равен  0x004C2CEA

первые 10 бит  дают 1

а оставшиеся 22 это 0b 00 1100 0010 1100 1110 1010  или 0хC2CEA или в десятичной 797 930 и как это интерпретировать или представить в виде   0,190241370360758 ну т.е. то что после точки ?

Просто возьмите в руки калькулятор и посчитайте: 0x004C2CEA/2^22 = 1.19024133682250977

Т.е. - получилось что и должно.

 

PS: Что такое Q-формат и как в нём работать - почитайте хотя-бы wiki:  https://en.wikipedia.org/wiki/Q_(number_format)

PPS: И ещё раз повторю: Так действовать имеет смысл только на CPU без FPU, и/или если нужна высокая скорость вычислений.

Имеет ли ваш CPU FPU - Вы так и не написали.

PPPS: В некоторых случаях даже на CPU с аппаратным FPU вычисления в fixed-point могут быть быстрее, чем во float. Или давать более точный результат (так как мантисса float = всего 24 бита, а в fixed-point она имеет длину 31 или 32 бит (для int/unsigned int ARM) и легко расширяется до бОльших величин если нужно).

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


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

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

 

Имеет ли ваш CPU FPU - Вы так и не написали.

 

нет не имеет , у меня gd32f103rc 

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

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


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

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

нет не имеет , у меня gd32f103rc 

Тогда тем более советую изучить Q-формат. Даже если производительность сейчас не особо важна - потом пригодится.

Там нет ничего сложного. Когда разберётесь, увидите насколько он эффективен.

 

PS: Если производительность кода не важна, можно конечно просто работать с float или double в режиме программной эмуляции.

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


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

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

нет не имеет , у меня gd32f103rc 

Изменено 47 минут назад

Что-то мне подсказывает, что переход в double будет дешевле делений/умножений/приведений.

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


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

31 minutes ago, dimka76 said:

почему в калькуляторах таких проблем не возникает ?

в bcd считают

http://files.righto.com/calculator/TI_calculator_simulator.html

 

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


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

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

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

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

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

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

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

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

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

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