Я не эксперт в программировании, и я столкнулся со следующей проблемой.
Мне нужно вычислить по модулю между числами с плавающей запятой A и B. Поэтому я использую fmod((double)A, (double)B). Теоретически, если A кратно B, то результат равен 0,0. Однако из-за цели точности с плавающей запятой A и B не совсем то число, которое я ожидал иметь. Тогда результатом вычисления по модулю будет не 0,0, а что-то другое. Что проблематично.
Пример: A=99999,9, но компилятор интерпретирует его как 99999,898. B=99,9, но компилятор интерпретирует это как 99,900002. Ожидается, что fmod(A,B) будет 0,0, но на самом деле дает 99,9.
Итак, вопрос: как вы используете, чтобы справиться с такой ситуацией?
Спасибо
1 ответ
Проблема в том, что:
A
– это не 99999.9
, а 99999,8984375 и
B
– это не 99.9
, а 99,90000152587890625 и
A mod B
равно 99,89691162109375
ОП получает правильный ответ на приведенные аргументы.
Нужно использовать разные дополнения.
Разумной альтернативой является преобразование аргументов в масштабированную степень 10, затем округление до целого числа, %
, обратно до с плавающей запятой и не- шкала.
Переполнение вызывает беспокойство.
Поскольку OP хочет обрабатывать числа с точностью до 0,1, масштабируйте на 10.
#include <float.h>
#include <stdio.h>
int main(void) {
float A = 99999.9;
float B = 99.9;
printf("%.25f\n", A);
printf("%.25f\n", B);
printf("%.25f\n", fmod(A,B));
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
printf("D = %.25f\n", D);
return 0;
}
Выход
99999.8984375000000000000000000
99.9000015258789062500000000
99.8969116210937500000000000
D = 0.0000000000000000000000000
Альтернатива
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
Масштабируйте, но пропустите часть преобразования integer
double a = round(A*10.0);
double b = round(B*10.0);
double m = fmod(a,b);
double D = m/10.0;
fmod
, ни любая другая разрывная функция не даст результатов, как если бы использовалась математика действительных чисел.
Похожие вопросы
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.
double
? Используйтеfmodf
для поплавковfloat
, всегда используйтеdouble
.