Форум: "Основная";
Текущий архив: 2003.04.17;
Скачать: [xml.tar.bz2];
ВнизОкругление Найти похожие ветки
← →
Vick (2003-03-31 16:06) [0]Доброго всем дня! Может кто знает, как в Делфи округлить число до 2-х знаков после запятой, при чем, чтобы округлялось в большую сторону, или нужно свое что-то писать, а то ф-ции типа FormatFloat и FloatToStrF, и т.д. округляют в меньшую сторону :((((
Заранее спасибо за ответ.
← →
Anatoly Podgoretsky (2003-03-31 16:10) [1]Значит что то/кто то поменял контрольное слово процессора.
← →
Vick (2003-03-31 16:11) [2]> Anatoly Podgoretsky
Это как? А как его на место вернуть?
← →
Anatoly Podgoretsky (2003-03-31 16:16) [3]Переинсталлировать Виндоус, если конечто ты точно описал и понял проблему. А так в системе есть сопроцессор, который занимается округлением, и который можно заставить округлять по разному, в том числе и в меньшую сторону и есть плохие программы, которые это сделают. Но мне кажется, что ты где то, что то перепутал.
← →
Андрей Сенченко (2003-03-31 16:20) [4]Только заменой процессора вместе с материнкой, памятью и клвиатурой. Монитор можешь оставить.
ну или написать FORMAT правильно
Например так:
Edit1.Text := FormatFloat("0.00",StrToFloat(Edit1.Text));
← →
Alexander Vasjuk (2003-03-31 16:20) [5]Vick ©
По правилам округления
до *.*5 округляется в меньшую сторону
а с *.*5 включительно - в большую
или я что то не понял
← →
Vick (2003-03-31 16:21) [6]> Anatoly Podgoretsky
Обижаешь девушку, начальник! :)))) Да ну на самом деле пишу FormatFloat("0.00", 9.245), получаю 9.24.
← →
Anatoly Podgoretsky (2003-03-31 16:26) [7]А теперь попробуй 9,255 и прочитай правила округления, я не зря сомневался, что путаешь.
Округление до четного!, потом нельзя одназначно сказать, что 9.245 хранится как 9.245000000000000000, а не 9.244999999999999999
Чмсла с плавующей запятой, не являются точными, в отличии от чисел с фиксированной запятой. А насчет программ я не шутил, такое встречается и Микрософт об этом предупреждает.
← →
Mystic (2003-03-31 16:30) [8]
function UpRoundTo(const AValue: Double; const ADigit: TRoundToRange = -2): Double;
var
LFactor: Double;
const
NINES = 0.999999999999999999999999999999999999999999999999;
begin
LFactor := IntPower(10, ADigit);
Result := Trunc((AValue / LFactor) + NINES) * LFactor;
end;
При этом
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Add("0.035 - " + FormatFloat("0.000", UpRoundTo(0.035)));
Memo1.Lines.Add("0.045 - " + FormatFloat("0.000", UpRoundTo(0.045)));
Memo1.Lines.Add("0.049 - " + FormatFloat("0.000", UpRoundTo(0.049)));
Memo1.Lines.Add("0.051 - " + FormatFloat("0.000", UpRoundTo(0.051)));
end;
возвращает
0.035 - 0,040
0.045 - 0,050
0.049 - 0,050
0.051 - 0,060
Это Вас удовлетворит?
← →
Vick (2003-03-31 16:31) [9]> Anatoly Podgoretsky
А могло это контрольное слово испортиться, когда комп круто завис?
← →
Alexander Vasjuk (2003-03-31 16:32) [10]Anatoly Podgoretsky © (31.03.03 16:26) Округление до четного!,
Русские правила - см. выше
IMHO в Delphi "русские правила".
9.245000000000000000, а не 9.244999999999999999
100%
← →
Anatoly Podgoretsky (2003-03-31 16:35) [11]Vick © (31.03.03 16:31)
Не конечно, да и нарваться на такую неприятную программу редкость, так что тебе дала проверка для 9,255
← →
Vick (2003-03-31 16:40) [12]Я выяснила, что это у меня навреное что-то с самим приложением, потому что создала новое и проделала то же самое - все нормально...
← →
Anatoly Podgoretsky (2003-03-31 16:44) [13]Тогда вполне возможно, что мое предположение насчет контрольного слова спопроцессора было верным.
← →
Alexander Vasjuk (2003-03-31 16:44) [14]Vick © (31.03.03 16:40)
:) Классный способ устранять ошибки! Надо бы свои программы переписать пару раз!
← →
Vick (2003-03-31 16:52) [15]Фигня происходит, когда я пишу
FormatFloat("0.00", (64.5 * cdsDOC_TABLESNACENKA.AsFloat) / 6),
где cdsDOC_TABLESNACENKA.AsFloat - это значение поля ClientDataSet, на самом деле оно равно 0.86, но судя по всему какую-то фигню передает... потому что если я пишу
FormatFloat("0.00", (64.5 * 0.68) / 6), то все нормально
← →
blackman (2003-03-31 17:09) [16]Удалено модератором
← →
Старшина (2003-03-31 17:29) [17]Проблема с cdsDOC_TABLESNACENKA.AsFloat
На самом деле там не 0.68
см. Anatoly Podgoretsky © (31.03.03 16:26)
← →
Anatoly Podgoretsky (2003-03-31 17:35) [18]Vick © (31.03.03 16:52)
ShowMessage(cdsDOC_TABLESNACENKA.AsFloat)
← →
NickBat (2003-03-31 18:14) [19]> округлить число до 2-х знаков после запятой,
> при чем, чтобы округлялось в большую сторону
_______________________________^^^^^^^
Нельзя ОКРУГЛЯТЬ в большую сторону! Можно или округлять по правилам или писать что-то свое. :))
А вообще-то у меня была похожая проблема: надо было отбрасывать десятые от копеек, причем именно отбрасывать, а не округлять.
Если пытаться делать такие комбинации через стандартные функции или писать свои с преобразованием чисел, то неизменно будут ошибки.
То есть они не постоянные, но на определенных числах, отображение которых на экране и в памяти компьютера разное - вылетают "грабли".
Выход нашел только в преобразовании числа в строку, сделать с ней что надо, а потом опять в число.
← →
Mystic (2003-03-31 18:34) [20]> Если пытаться делать такие комбинации через стандартные
> функции или писать свои с преобразованием чисел, то неизменно
> будут ошибки.
У Д. Кнута есть по этому поводу цитата: что все законы, которые теоретически открыли математики, не имеют практического применения: если сложить числа в столбик, а потом сложить их в обратном порядке --- то все время получаются разные результаты.
← →
Vick (2003-04-01 10:18) [21]Доброго всем утра!!!
Обнаружила такую вещь, что если написать
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FormatFloat("0.00", 9.245));
end;, то получаем результат 9.25,
а если так
procedure TForm1.Button1Click(Sender: TObject);
var fl: double;
begin
fl:=9.245;
ShowMessage(FormatFloat("0.00", fl));
end;, получается 9.24.
Как это объяснить?
← →
Vick (2003-04-01 10:25) [22]Что самое интересное, что
procedure TForm1.Button1Click(Sender: TObject);
var fl: Extended;
begin
fl:=9.245;
ShowMessage(FormatFloat("0.00", fl));
end;, получается 9.25.
Возникает другой вопрос, как из real или double преобразовать в Extended?
← →
Anatoly Podgoretsky (2003-04-01 10:40) [23]Очень просто, первый случай - высчитывается на этапе компиляции, второй случай на этапе выполнения. При этом в ячейке памяти fl совсем не обязательно 9.2450000000000000, проверить можно в отладчике, поставив точку останова и начать Ctrk+F5 на слове fl, тогда узначешь точное значение в памяти.
При переходе на повышенную точность Extended, представление немного другое, это означает, что данное число нельзя представить в виде двоичной дроби, это примерно так же как для десятичной дроби 1/3
← →
BorisKb (2003-04-01 10:44) [24]Найди на сайте http://delphi.vitpc.com/index.htm отличную статью про округление и вообще про арифметику в Delphi. Не найдешь - могу выслать.
← →
Anatoly Podgoretsky (2003-04-01 10:50) [25]http://www.delphikingdom.ru/helloworld/reals.htm
← →
BorisKb (2003-04-01 10:51) [26]<Anatoly Podgoretsky > - Она самая :)
← →
Vick (2003-04-01 11:00) [27]> BorisKb ©
Пришли пожалуйста, пролистала все статьи ненашла там.
← →
Anatoly Podgoretsky (2003-04-01 11:09) [28]Vick © (01.04.03 11:00)
Ну я же дал прямую ссылку
← →
Vick (2003-04-01 11:12) [29]Нашла, громное спасибо!!!!
← →
Спрашивающий (2003-04-02 02:34) [30]Я согласен с NickBat © что работать нужно не с числами а со строкой и кстати это не так то просто как кажется на первый взгляд. Я такую функцию писал около нелели! Хотя поверьте со строками работать умею. Пример не привожу потрму что он соизмерим с исходником проги. И собственно функций используется много, так как много в этом деле подводных камней. Со стандартными функциями округления ничего не сделаете путного для вашего примера.
← →
Alexander1966 (2003-04-02 13:20) [31]У Борланда есть такой хитрый тип: BCD
он округляется по правилам математики.
Пример на C++Builder
double Round(double v,int prec)
{
bcd a=bcd(v,prec); // Вот оно округление
double aa=real(a); // обратно в нужный тип
return aa;
}
← →
Anatoly Podgoretsky (2003-04-02 13:33) [32]С BCD проблем не бывает, поскольку абсолютная точность, а не относительная, но поддержка BCD появилась только в Д6 и то не знаю в каком виде, есть еще предопределенный тип Currency, это BCD 20.4
← →
Style (2003-04-02 13:33) [33]begin
Caption := FloatToStr(FlRound(3.754545,2));
end;
function FlRound(Fl: double; M: Integer): double;
var
z,i: integer;
begin
z := 1;
for i:= 1 to M do
z:= z * 10;
Result := Ceil(fl * z) / z;
end;
← →
NickBat (2003-04-02 14:35) [34]> Style
Если протестировать твой способ на реальных цифрах, то в некоторых случаях возможны ошибки. :(
← →
Style (2003-04-02 14:40) [35]>> Ты имеешь в виду Тип Real????
← →
NickBat (2003-04-02 15:01) [36]Нет :)) Я говорил о рабочей программе с которой работает несколько пользователей.
Например в программе произошел подсчет цены за какой-то товар.
Получилось, например, 13.3456 рублей - то есть для бухгалтерии надо показать: 13 руб. 34 коп.
И вот при твоем способе периодически вылетают ошибки, которые зависят от внутреннего представления полученной суммы в компьютере.
← →
Nic_B (2003-04-02 15:46) [37]Я пользуюсь такой функцией (не помню уже где выдрал :)))
Вроде пока глюков не наблюдалось
function TPLAT.RoundEx( X: Double; Precision : Integer ): Double;
{Precision :
1 - до целых
10 - до десятых
100 - до сотых
...
}
var ScaledFractPart, Temp : Double;
begin
ScaledFractPart := Frac(X)*Precision;
Temp := Frac(ScaledFractPart);
ScaledFractPart := Int(ScaledFractPart);
if Temp >= 0.5 then ScaledFractPart := ScaledFractPart + 1;
if Temp <= -0.5 then ScaledFractPart := ScaledFractPart - 1;
RoundEx := Int(X) + ScaledFractPart/Precision;
end;
← →
NickBat (2003-04-02 16:48) [38]Одно время пользовался примерами приведенными Nic_B и Style. По логике они похожи. Периодически прибегали пользователи и говорили - "вижу не ту цифру".
Сейчас пользуюсь таким решением:
ss:=FloatToStr(Sum);
if pos(",",ss)>0 then delete(ss,pos(",",ss)+1+Sign,255);
Result:=StrToFloat(ss);
Где разделитель целой и дробной части "," а Sign - сколько знаков после запятой оставить.
← →
pasha676 (2003-04-02 17:25) [39]2NickBat
А не пробывал умножать брать trunc и делить. Имхо ничуть не хуже, а решение более простое.
← →
NickBat (2003-04-02 17:36) [40]Ухх..
Пусть есть число: 14.34
В компьютере оно может храниться как 14.339999999999, но отражаться на экране оно будет как 14.34!!
Если попробывать отбросить третий знак после запятой, то получим на выходе 14.33 - вот и вся математика.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2003.04.17;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.012 c