Easyelectronics.ru

Электроника для всех
Текущее время: 20 июл 2018, 09:23

Часовой пояс: UTC + 5 часов



    • JLCPCB - Платы прототипов всего за 2$ c бесплатной доставкой (при первом заказе)
    • 10 PCBs за $2 для 2 слоев, $15 для 4 слойной, $74 для 6 слойной платы.
    • Крупнейший китайский производитель прототипных плат. 290000+ клиентов & 8000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин радиодеталей.

Начать новую тему Ответить на тему  [ Сообщений: 98 ]  На страницу Пред.  1, 2, 3, 4
Автор Сообщение
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 05 июл 2018, 20:51 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
Я не просил переводить в десятичное число, мне нужно изменить степень - это немного иное.
Если просто переводить матису плавучки в десятичное число - получится откровенная фигня.

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 05 июл 2018, 20:51 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
AVI-crak, вычисляете порядок бит за битом (умножая float-число на соответствующую степень 10), вестимо. За 9 шагов должны найти.
Грубо говоря, число больше 1e256 - умножаете на 1e-256, e+=256
больше 1e128 - умножаете на 1e-128, e+=128
и так далее (ну, это для положительных порядков, для отрицательных аналогично)
Может понадобиться небольшая табличка (1e-256, 1e-128 ... 1e-1; 1e1 ... 1e128, 1e256).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 05 июл 2018, 21:17 
Старожил
Аватара пользователя

Зарегистрирован: 28 дек 2011, 11:24
Сообщения: 3681
Откуда: г. Липецк
Double это же стандарт IEEE754. Может это поможет?
Учтите также что Double имеет несколько видов:
- Нормализованные (normal)
- Денормализованные (subnormal)
- -0 и +0 (отрицательный и положительный ноль)
- NaN (не числа)
Это все нужно распознавать и обрабатывать.


Вложения:
Double_IEEE754_.png
Double_IEEE754_.png [ 2.62 Кб | Просмотров: 353 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 01:33 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 750
Прозвучал вопрос, почему это UB:
float_text[ofline++] = float_text[ofline];

Дело в том, что стандарт не регламентирует порядок вычисления независимых выражений.
Неизвестно, какое выражение будет вычислено раньше,
float_text[ofline++], или float_text[ofline].

Таким образом, выражение может быть прочитано как:
a)
char& c = float_text[ofline];
char& d = float_text[ofline++];
d = c;

б)
char& d = float_text[ofline++];
char& c = float_text[ofline];
d = c;

Как вы понимаете, это ни одно и тоже.
Если выражение слева будет вычеслено раньше, выражение справо будет взято по адресу ofline+1. Если наоборот, то по адресу ofline.

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 01:56 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
Mirmik, я уже говорил: всё ещё хуже. "Выбор между первым и вторым варинтом целиком на совести компилятора" - это тьфу, implementation defined behavior. В данном же случае именно undefined behavior, и компилятор модет сделать что угодно. Например, может вызвать функцию, вызова которой в коде вообще нет: https://m.habr.com/company/infopulse/blog/338812/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 02:18 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 750
Не надо демонизировать компилятор. Undefined behavior может проявляться по разному, но в рамках логики.
В этом коде нет никаких предпосылок к вызову левых функций. Потому что ни одного вызова тут нет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 02:28 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 750
Вообще, надо правильно понимать, что такое undefined behavior.
undefined behavior значит, что стандарт не регламентирует поведение программы в случае, если вы совершите то или иное действие. Но это не означает, что поведение нельзя предсказать.

Вот пример забавного undefined behavior.

har arr[3][5] = {"Hello","World"};
char* ptr = *arr + 6;
*ptr = 'M';
printf(arr);

Любой нормальный сишник понимает, что код коректен, но формально тут undefined behavior, потому что адресная арифметика над многомерными масивами стандартом не определена.

upd: более содержательный пример.


Последний раз редактировалось Mirmik 11 июл 2018, 06:00, всего редактировалось 4 раз(а).

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 02:32 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 750
Что до implementation defined, это значит, что стандарт в целом регламентирует последствия вашего действия, но что конкретно будет сделано для достижения результата, оставляется на совести компилятора.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 05:21 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 1127
Откуда: Китай, Пекин
Цитата:
формально тут undefined behavior, потому что

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 05:53 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 750
И все мы прекрасно это знаем... Но, если внимательно читать стандарт, окажется, что такой код вне закона... Ну вот баг стандарта такой, известен...
Я это к тому, что не всякий undefined behavior обязательно сотрет вам корень.

undefined behavior - это о соответствии стандарту, ничего более. Если код соответствует, у вас есть гарантия. Нет... Никто ничего не обещал.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 06:13 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 1127
Откуда: Китай, Пекин
arr[3][5] обычняй массив длинной 15.
arr[15][1] ==arr[15]==arr[1][15]

обычный.
массив.

всё более чем предопределено

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

undefined behavior это когда вызывают free на неправильный указатель например.
Цитата:
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 08:55 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
Устранил серую ошибку.

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 09:05 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
anakost писал(а):
Учтите также что Double имеет несколько видов:

Всё это есть в float. Просто числа больше, и константы выше.
Я думаю что получится отдельно разобрать float и double на критических пределах - где заранее известен результат печати.
А полученную матнтису и порядок обрабатывать как два независимых 32бит числа - одинаково для двух форматов. Один фиг, печать всех чисел double после запятой - только сумасшедшим нужно.
Придётся добавить сокращённую таблицу, с терпимым шагом, например 32. Получится 64 константы для double, и 8 для float. Это намного меньше чем в оригинале (4к)

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 10:11 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
AVI-crak, почему 64? Я ж написал выше про вычисление десятичного порядка бит за битом (типа половинного деления), 17 констант надо, считая единицу (и никакого "терпимого шага", после 9 шагов получаете результат)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 11:33 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
aamonster писал(а):
17 констант надо, считая единицу

Честно говорю - не понимаю.
Число приходит в двоичном режиме, все операции в двоичном представлении, десятичный выхлоп как побочный продукт. 64 - потому что так проще выбрать из таблицы готовое значение, но приближаться к требуему числу придётся максимум за 31 шаг. При резком всплытии - будет явно прогнозируемая потеря данных.
Как можно сделать иначе? На пальцах плиз.

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 13:18 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
На пальцах для чисел больше 1:
e = 0 // порядок
if x>1e256 {
e+=256
x/=1e256
}
if x>1e128 ...
...
Итого 8 шагов, 8 констант.
Если деление заменить на умножение - ещё 8 констант добавится, но они всё равно нужны для чисел меньше 1.

Записать циклом и разобрать случаи x<1 и x<0 - уже сами :-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 14:09 
Старожил
Аватара пользователя

Зарегистрирован: 28 дек 2011, 11:24
Сообщения: 3681
Откуда: г. Липецк
Пришлось раз решать несколько другую задачу при парсинге загружаемого файла с данными Double. Надо было зараннее обнаружить NaN и отметить маркером. Код на Object Pascal, но думаю будет понятен всем.
Код:
const
  cNAN = $7F800000;

  if PLongInt(@After.trValue)^ and cNAN = cNAN then AddMark(assErrorVal);

@After это указатель на блок данных (запись), trValue это значение Double, которое надо проверить. AddMark(assErrorVal) функция устанавливающая маркер assErrorVal.
Double предварительно приводится к виду 32 битного LongInt.
P.S. Давно это было, и я ошибся, trValue это Single, эвивалент Float в 32 битной системе, извините.


Последний раз редактировалось anakost 11 июл 2018, 19:52, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 14:41 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
aamonster писал(а):
Итого 8 шагов, 8 констант.

В подобных операциях с порядком нету смысла. Потому как двоичное значение мантисы не совпадает с десятичным требуемым результатом. Кроме одного единственного значения порядка (равное нулю) - когда можно вести преобразование почти без промежуточных умножений. Именно для этого таблица составляется с привязкой к двоичному представлению порядка.

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 15:04 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
AVI-crak, все операции делаются с числом _целиком_ - не отдельно с порядком, а именно целиком. Деление в псевдокоде - это floating-point деление со всеми его сложностями.
e - десятичный порядок (который нам нужно найти).

Потеря точности - только из-за округления при 8 делениях (или умножениях, всегда есть смысл заменять деления на умножения)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 16:25 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
aamonster писал(а):
AVI-crak, все операции делаются с числом _целиком_

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

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 11 июл 2018, 17:17 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
AVI-crak, я в своей жизни столько раз писал половинное деление, что проверять на бумажке уже не требуется.
И битовое представление для проверки алгоритма тоже не нужно: он работает с _числами_, используя лишь операции деления (или умножения) и сравнения. Представление чисел несущественно: можете использовать IEEE, можете представление с фиксированной точкой, можете какую-нибудь экзотику. Достаточно реализовать две операции - деления и сравнения.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 12 июл 2018, 00:15 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 455
aamonster писал(а):
AVI-crak, я в своей жизни столько раз писал половинное деление...

Я наверное со стеной разговариваю...
В моём мире двоичное и десятичное представление с порядком - имеет возможность прямого преобразования через достаточно громоздкую формулу. С рекурсией приближения и обязательными циклами. Формула хоть и основана на стандартных математических функциях - но в реалии arm чипов будет выполняться программно, и значительно дольше моего алгоритма.

У вас-же приближение за 9 шагов и минимум констант для диапазона 2045 позиций порядка числа формата double - без явных доказательств.
Из чего можно сделать вывод - что вы не смогли понять даже мой алгоритм.

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Слепая печать float/uint(8-32)_t/int(8-32)_t замена printf
СообщениеДобавлено: 12 июл 2018, 01:28 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2470
Откуда: Санкт-Петербург
Ну, определённо со стеной, не со мной :-).
2048 позиций двоичного порядка - это 617 позиций десятичного. Сколько шагов половинного деления надо, чтобы найти число от -308 до 308?

P.S. И да, получится 9 делений (или умножений) double, они дорогие. Вероятно, можно уменьшить их количество, увеличив таблицу - но я бы не стал, помимо таблицы - это неоправданно усложнит код, так делать не следует.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 98 ]  На страницу Пред.  1, 2, 3, 4

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB