Математический форум Math Help Planet
http://mathhelpplanet.com/

Проблема с числами с плавающей запятой
http://mathhelpplanet.com/viewtopic.php?f=44&t=55188
Страница 1 из 1

Автор:  dersu-uzalah [ 05 июл 2017, 10:14 ]
Заголовок сообщения:  Проблема с числами с плавающей запятой

Всем здравствуйте.
Есть некая прога, написанная на С, в которой интенсивно используются числа с плавающей запятой в формате IEEE64. Прога написана для микроконтроллера семейства HCS08 Freescale. Для написания и компиляции использовалась среда CodeWarrior IDE ver.5.9.0. Думаю что это не имеет значения. На определенном этапе было замечено, что происходит искажение чисел, значение которых превышает 65536. Например, 65535,9999 таким и остается, а 65536 само по себе превращается в 65536.0004. Чем больше число, тем больше искажение. Все в сторону увеличения.
Код примерно такой:
double a;
a = 65535,9999;
OutLCD (a);
a+=0.0001;
OutLCD (a);
При первом выводе на дисплей получаем ожидаемое 65535,9999
А при 2-м: 65536.0004
В системе имеется файл float.h (прилагается), который вроде как задает конфигурацию чисел с плавающей запятой. Может есть смысл поиграться с его настройками?
Буду бесконечно признателен за любые идеи, в чем проблема, и как это можно было бы победить.

PS. Файл не добавляется почему-то, копирую его сюда:
/*****************************************************
float.h - ANSI-C library: floating point format
----------------------------------------------------
Copyright (c) Metrowerks, Basel, Switzerland
All rights reserved
Do not modify!
*****************************************************/

#ifndef _H_FLOAT_
#define _H_FLOAT_

#ifdef __cplusplus
extern "C" {
#endif

#if !defined(__HIWARE__) && defined(__MWERKS__) && defined(__PPC__)
/* Metrowerks PowerPC compiler does not define the stuff below */
#define __FLOAT_IS_IEEE32__
#define __DOUBLE_IS_IEEE64__
#endif

/**** Rounding Mode */

#define FLT_ROUNDS -1
#define FLT_RADIX 2

/**** float */

#ifdef __FLOAT_IS_IEEE32__

#define FLT_MANT_DIG 24
#define FLT_DIG 6
#define FLT_MIN_EXP -126
#define FLT_MIN_10_EXP -37
#define FLT_MAX_EXP 127
#define FLT_MAX_10_EXP 38
#define FLT_MAX 3.402823466E+38F
#define FLT_EPSILON 1.19209290E-07F
#define FLT_MIN 1.17549435E-38F

#endif

#ifdef __DOUBLE_IS_IEEE32__
/**** double */

#define DBL_MANT_DIG FLT_MANT_DIG
#define DBL_DIG FLT_DIG
#define DBL_MIN_EXP FLT_MIN_EXP
#define DBL_MIN_10_EXP FLT_MIN_10_EXP
#define DBL_MAX_EXP FLT_MAX_EXP
#define DBL_MAX_10_EXP FLT_MAX_10_EXP
#define DBL_MAX FLT_MAX
#define DBL_EPSILON FLT_EPSILON
#define DBL_MIN FLT_MIN

#endif

#ifdef __DOUBLE_IS_IEEE64__
/**** double */

#define DBL_MANT_DIG 53
#define DBL_DIG 15
#define DBL_MIN_EXP -1022
#define DBL_MIN_10_EXP -307
#define DBL_MAX_EXP 1023
#define DBL_MAX_10_EXP 308
#define DBL_MAX 1.7976931348623157E+308
#define DBL_EPSILON 2.2204460492503131E-16
#define DBL_MIN 2.2259738585972014E-308

#endif



#ifdef __FLOAT_IS_DSP__
/* DSP float */

#define FLT_MANT_DIG 16
#define FLT_DIG 4
#define FLT_MIN_EXP -32768
#define FLT_MIN_10_EXP -9863
#define FLT_MAX_EXP 32767
#define FLT_MAX_10_EXP 9863
#define FLT_MAX 0.9999695E+9863F
#define FLT_EPSILON 3.051757E-05F
#define FLT_MIN 0.9999695E+9863F

#endif

#ifdef __DOUBLE_IS_DSP__
/**** double */

#define DBL_MANT_DIG 16
#define DBL_DIG 4
#define DBL_MIN_EXP -32768
#define DBL_MIN_10_EXP -9863
#define DBL_MAX_EXP 32767
#define DBL_MAX_10_EXP 9863
#define DBL_MAX 0.9999695E+9863F
#define DBL_EPSILON 3.051757E-05F
#define DBL_MIN 0.9999695E+9863F

#endif

/**** long double */

#define LDBL_MANT_DIG DBL_MANT_DIG
#define LDBL_DIG DBL_DIG
#define LDBL_MIN_EXP DBL_MIN_EXP
#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
#define LDBL_MAX_EXP DBL_MAX_EXP
#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
#define LDBL_MAX DBL_MAX
#define LDBL_EPSILON DBL_EPSILON
#define LDBL_MIN DBL_MIN


#ifdef __cplusplus
}
#endif

#endif

/*****************************************************/
/* end float.h */

Автор:  SAVANTOS [ 05 июл 2017, 22:04 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Вы можете поменять компилятор или другой микроконтроллер и попробовать свою программу снова?

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

Редактировать файлы из стандартной библиотеки не рекомендую.

Автор:  dersu-uzalah [ 05 июл 2017, 22:23 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Спасибо за Ваш ответ, SAVANTOS. На другом микроконтроллере (и соответственно с другим компилятором) все работает как надо. Но мне нужно чтобы именно на этом работало. Файлы из стандартной библиотеки всегда можно вернуть в исходное состояние. Однако таким путем мне не удалось ничего добиться.

Автор:  bimol [ 05 июл 2017, 22:27 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Такой вариант, заменить
a+=0.0001;
на
double b
b=0.0001;
a+=b;

Автор:  Xmas [ 05 июл 2017, 23:39 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Не помешает проверить, установлен ли флажок на 32-битные "плавающие точки".

Однажды на каком-то компиляторе встречал "по умолчанию" 24-битные плавающие. Нужно было явно указывать -DIEEE32 или типа того, чтобы включилось полномасштабное вычисление.

Автор:  SAVANTOS [ 06 июл 2017, 10:06 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Нашёл похожую проблему на форуме NXP. Там говорится, что при создании проекта есть выбор-какой формат использовать для типов float и double. У вас было что-то похожее?

Скорее всего такие ошибки из-за того что используется одинаковый формат представления для float и double.


https://community.nxp.com/thread/383411

Автор:  dersu-uzalah [ 06 июл 2017, 13:33 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

bimol, я показал здесь лишь простейший пример. На самом деле оно всегда добавляет эти свои 0.0004
Xmas, при создании проекта все флажки были установлены как надо: double - IEEE64
SAVANTOS, это я пытался что-то у них выяснить, но такой "обход" как они предлагают, мне не подходит.
Всем спасибо!

Автор:  bimol [ 06 июл 2017, 14:18 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Я к тому, что все константы надо объявлять через переменные double или явно указывать, что константа double
Иначе проблема зарыта глубоко.

Автор:  dersu-uzalah [ 11 июл 2017, 07:51 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

Выяснились подробности.
double val1;
double val2;
val1 = 65535.9999;
val2 = 65536.0000;
sprintf (lbuf,"%5.4f", val1);
sprintf (lbuf,"%5.4f", val2);
После выполнения 1-го sprintf, в lbuf[] заносится строка "65535.9999", после выполнения 2-го: "65536.0004"

Автор:  Xmas [ 11 июл 2017, 09:15 ]
Заголовок сообщения:  Re: Проблема с числами с плавающей запятой

dersu-uzalah

Очень похоже на баг компилятора. В 65536.000 вообще неоткуда взяться 0.0004 - у этого числа в двоичном плавающем формате в мантиссе одни нули и ничего кроме нулей.

Так что Вы тут ни при чём. Это всё компилятор.

Страница 1 из 1 Часовой пояс: UTC + 3 часа [ Летнее время ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/