Сейчас на форуме: _MBK_ (+6 невидимых)

 eXeL@B —› Вопросы новичков —› Что за казус с FloatToStrF?
Посл.ответ Сообщение

Ранг: 6.0 (гость), 1thx
Активность: 0.010
Статус: Участник

Создано: 09 декабря 2010 17:05
· Личное сообщение · #1

Хотел поместить вопрос в раздел "Программирование", но прочитав правила, пишу здесь.
И так, в чем суть.
Нужно создать текстовый файл из фала данных типа Single. В общих чертах: в одном столбце, шаг по оси координат, в другом - значение. Вроде все просто и обыденно. Читаю из файла данных, перевожу в строку с помощью FloatToStrF и пишу в текстовый файл. Теперь собственно вопрос! Шаг квантования по оси координат 0.2, то есть ...100.0; 100.2; 100.4 и т.д. Но при записи в текстовый файл получается следующее:

100.0
100.2
100.4
...
...
...
120.3
120.5 // Хотя отладчик показывает в значении, 120.57(то есть, вроде ф-я должна округлить до 120.6)
И далее снова
166.4
166.6
...

В гугле ни чего не нарыл (с первых страниц).
Мне нужно, что бы все было четко (четно)
Если кто сталкивался, подскажите, как эту траблу исправить?




Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 09 декабря 2010 17:20
· Личное сообщение · #2

Функия форматирования строки из числа не делает округления. Быстрее всего в формате описан вывод одного знака после запятой, что собственно и происходит. То есть до преобразования числа в строку нужно его округлить до желаемой точности.

-----
Следуй за белым кроликом





Ранг: 793.4 (! !), 568thx
Активность: 0.740
Статус: Участник
Шаман

Создано: 10 декабря 2010 06:41
· Личное сообщение · #3

Округление в делфи тоже не по общему стандарту работает. Для точных вычислений я использую вот эту функцию:

Code:
  1. function RoundEx(X: Double; Precision: Integer ): Double;
  2. {
  3. Precision :
  4. 1 - до целых
  5. 10 - до десятых
  6. 100 - до сотых
  7. ...
  8. }
  9. var
  10.   ScaledFractPart, Temp: Double;
  11. begin  
  12.   ScaledFractPart := Frac(X) * Precision;
  13.   Temp := Frac(ScaledFractPart);
  14.   ScaledFractPart := Int(ScaledFractPart);
  15.   if Temp >= 0.5 then
  16.     ScaledFractPart := ScaledFractPart + 1;
  17.   if Temp <= -0.5 then
  18.     ScaledFractPart := ScaledFractPart - 1;
  19.   RoundEx := Int(X) + ScaledFractPart / Precision;
  20. end;


-----
Yann Tiersen best and do not fuck





Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 10 декабря 2010 09:58 · Поправил: neomant
· Личное сообщение · #4

А так:
Code:
  1. ...
  2. SetRoundMode(rmNearest);
  3. := Round(* 10) / 10;
  4. ...

округление x до десятых.

-----
Следуй за белым кроликом





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 10 декабря 2010 10:18
· Личное сообщение · #5

К слову говоря, не рекомендуется свои функции обзывать существующими именами и добавлять постфикс Ex. В какой-нить новой версии они могут появиться, может быть оказия.



Ранг: 6.0 (гость), 1thx
Активность: 0.010
Статус: Участник

Создано: 12 декабря 2010 06:47
· Личное сообщение · #6

neomant пишет:
Функия форматирования строки из числа не делает округления.

Посмотрев некоторые примеры и описания вижу, что вроде как округляет. Вот что видно в отладчике:
х строка
69,79 -> "69.8" // округляет
69,59 -> "69.6" // округляет
69,39 -> "69.3" // ни хрена


Быстрее всего в формате описан вывод одного знака после запятой, что собственно и происходит.
Так и есть.

Спасибо за ответы и советы. Буду внедрять.
Тему пока закрывать не буду.




Ранг: 164.6 (ветеран), 65thx
Активность: 0.120
Статус: Участник
Волшебник

Создано: 12 декабря 2010 08:04
· Личное сообщение · #7

Code:
  1.   x := 69.79; // -> "69.8" // округляет
  2.   y := x;
  3.   Memo1.Lines.Add(FloatToStrF(x, ffNumber, 7, 2) + ' -> '
  4.     + FloatToStrF(y, ffNumber, 3, 1));
  5.   x := 69.39; // -> "69.3" // ни хрена
  6.   y := x;
  7.   Memo1.Lines.Add(FloatToStrF(x, ffNumber, 7, 2) + ' -> '
  8.     + FloatToStrF(y, ffNumber, 3, 1));
  9.   x := 69.59; // -> "69.6" // округляет
  10.   y := x;
  11.   Memo1.Lines.Add(FloatToStrF(x, ffNumber, 7, 2) + ' -> '
  12.     + FloatToStrF(y, ffNumber, 3, 1));

Код проверялся в Dephi 7 с разными типами вещественных переменных, работает корректно.
Показывайте свой код.

-----
Следуй за белым кроликом




Ранг: 6.0 (гость), 1thx
Активность: 0.010
Статус: Участник

Создано: 13 декабря 2010 14:50 · Поправил: Spirt_Fire
· Личное сообщение · #8

neomant пишет:
Показывайте свой код.

Показывать то особо нечего. Простейший код. Вместо ffNamber использую ffFixed, потому как
лишние запятые-точки мне ненужны.
Взял, тупо, переустановил Delphi и все заработало. Все округляется как надо, прикладываю пару скринов.

While not Eof(Файл данных) do
begin
Read(Файл данных, znachenie);
stroka1:=FloatToStrF(start, ffFixed, 7,1);
stroka2:=FloatToStrF(znachenie, ffFixed, 7,4);
writeln(ФайлTXT,' ',stroka1,' ',stroka2);
start:=start+step;
...
...

8954_13.12.2010_CRACKLAB.rU.tgz - Округляет.bmp


 eXeL@B —› Вопросы новичков —› Что за казус с FloatToStrF?
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати