• rosl (09.03.17 07:23) [0]
    Такой вопрос возник:
    имеем 3 поля (float). в них данные:

    поле      значение
    P1 -         0,022
    P2 -         60,7
    P3 -         587

    провожу расчет:
    ADOTable.fields[0].value*ADOTable.fields[0].value/ADOTable.fields[0].value
    результат 0,0023
    но мне нужно, чтоб после запятой было 14 знаков.
    должно получиться 0.00227495741056
    от этого значения зависит дальнейший расчет. в оконцовке (если используется 0,0023 вместо 0.00227495741056) результат не верен на 2 сотых.
  • rrrrr © (09.03.17 08:36) [1]
    во первых неизвестно какая размерность поля и что там на самом деле лежит
    во вторых tfield.value это variant/double у которого значащих 15 цифр
    в третьих при делении точность дабла никуда не девается и не округляется сама по себе
    в четвертых есть format(%x,nf)
  • Pavia © (09.03.17 08:40) [2]

    > ADOTable.fields[0].value*ADOTable.fields[0].value/ADOTable.
    > fields[0].value

    Даже формулу скопировать не могут!

    В Delphi нет типа float зато есть single, double, real, extended
    Это числа с плавающей точкой и вычисления в них идут по правилам IEEE 754 вот и читайте про этот формат.

    Как вы выводите результат в текстовый формат?

    > от этого значения зависит дальнейший расчет. в оконцовке
    > (если используется 0,0023 вместо 0.00227495741056) результат
    > не верен на 2 сотых.

    Не на 2 сотых, а на 23 миллионных.


    > но мне нужно, чтоб после запятой было 14 знаков.

    Какой тип данных вам нужен?
    https://ru.wikipedia.org/wiki/Число_с_плавающей_запятой

    Но 14 знаков это бесполезные данные. Всё равно у вас погрешность входных данных составляет 0,5*10^-5 значащих цифр. Бессмысленно увеличивать точность внутренних расчётов, так как результат не будет точнее чем входные данные.
  • rosl (09.03.17 09:12) [3]
    наверное плохо объяснил...
    тогда так:
    расчет в несколько действий. из за округлений, КОНЕЧНЫЙ РЕЗУЛЬТАТ не идет на 2 сотых (а это 2 копейки, в реальности)

    есть весь расчет в EXCEL, там все работает как надо.
    действие первое:
    0,020*60,7/587
    делаю:
    s: currency;
    s:=ADOTable1.Fields[1].AsFloat*ADOTable1.Fields[2].AsFloat/ADOTable1.Fields[3]AsFloat;
    (постом выше VALUE вместо AsFloat - эксперементировал)
    выдает результат - 0,0021 (в excel 0.00206814310051107) - в принципе правильно (округлил)
    но при следующем действии:
    s*1*587 выдает 1,2327 , в excel этот результат 1,2140
    так вот, пробую в excel 0.00206814310051107 заменить на 0,0021 выходит 1,2327
    вот они 2 сотых
    и так далее...
    тип полей сделал float. где рыть?
    так что 14 знаков - это бесполезные данные не в моём случае
  • rrrrr © (09.03.17 09:19) [4]
    выдает результат - 0,0021 (в excel 0.00206814310051107)

    asFloat из поля - это Double
    и там не 0,0021
    0,0021 это строка '0,0021' которую ты видишь после floattostr

    а реальная точность дабла - 15 значащих

    поэтому все дальнейшие выводы и логика неверные
  • rosl (09.03.17 09:36) [5]
    тогда не пойму.
    0.00206814310051107*587 = 1,2140
    0,0021                     *587 = 1,2327

    как быть?
  • Dimka Maslov © (09.03.17 09:47) [6]

    > как быть?


    В инженерных расчётах (не знаю как в бухгалерских) принято иметь три значащих цифры, округляя в большую сторону если последняя цифра 6..9, в меньшую сторону когда 0..4, а если последняя цифра 5 округлять до чётной
    0.00206814310051107 > 0.00207
    0.00206423238961768 > 0.00206
    0.00206522029076111 > 0.00206
    0.00205556467154581 > 0.00206

    В отдельных случаях принято увеличивать точность до 5-6 значащих цифр.
  • rrrrr © (09.03.17 09:50) [7]
    >0.0021 * 587 = 1,2327

    как и в экселе?
    да, как и в экселе.

    считает одинаково? одинаково.

    и в чем твоя печаль?
  • Dimka Maslov © (09.03.17 09:52) [8]

    > и в чем твоя печаль?


    0.0021 - это 2 (две) значащих цифры, а не четыре, как многие могут подумать.
  • rrrrr © (09.03.17 10:03) [9]
    ShowMessage(Format('%1.14f',[0.022 * 60.7 / 587]));
  • rrrrr © (09.03.17 10:05) [10]
    и снова, в чем твоя печаль?

    в том что первую строчку первого ответа не читаем?
  • rosl (09.03.17 10:16) [11]
    ShowMessage(Format('%1.14f',[0.022 * 60.7 / 587]));
    спасибо за наводку.
    видимо "косяк" в полях? какой тип поставить? sql
    0.022 * 60.7 / 587 = 0.00227495741056
    но если я подставляю переменные (поля со значениями) = 0,0023
  • Inovet © (09.03.17 16:04) [12]
    > [11] rosl   (09.03.17 10:16)
    > какой тип поставить? sql

    Деньги надо хранить в целых (с фиксированной точкой), считать в плавающей, каждый раз приводя при сохранении к целым (с фиксированной точкой). При округлении тоже может быть неожиданно, так что надо принимать специальные меры.
    http://www.delphikingdom.com/asp/viewitem.asp?catalogID=374
    и там же есть про функции округления для денег.
  • Inovet © (09.03.17 16:06) [13]
    DecimalRounding_JH1
  • rosl (09.03.17 19:54) [14]
    Всем спасибо за ответы, разобрался

    var
    s: Real;
  • Германн © (10.03.17 01:50) [15]

    > rosl   (09.03.17 19:54) [14]
    >
    > Всем спасибо за ответы, разобрался
    >
    > var
    > s: Real;
    >

    Хреново разобрался, если решил использовать тип Real.
  • rosl (10.03.17 18:20) [16]
    >Хреново разобрался, если решил использовать тип Real.

    срочно нужно было. а real помог
    мне на данный момент нужен быстрый результат
Есть новые Нет новых   [118456   +61][b:0][p:0.001]