【问题标题】:Error on FormatFloat(#,##0.00, var_number) and Format('%n', var_number) Rounding-off to ThousandsFormatFloat(#,##0.00, var_number) 和 Format('%n', var_number) 错误四舍五入到千位
【发布时间】:2020-10-25 00:56:20
【问题描述】:

FormatFloat(#,##0.00, var_number) 和 Format('%n', var_number) 给了我一个四舍五入的结果。为什么会这样?我的代码有问题吗?

我在下面做了一些Minimum Reproducible Example 供您参考。 我在这里得到的结果是 12 而不是 12,345.00。请让我知道我在这里错过了哪些地方和内容。

FMX 程序:

unit Unit9;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
  FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf,
  FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
  FireDAC.Phys, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef,
  FireDAC.Stan.ExprFuncs, FireDAC.FMXUI.Wait, FireDAC.Stan.Param, FireDAC.DatS,
  FireDAC.DApt.Intf, FireDAC.DApt, Data.Bind.EngExt, Fmx.Bind.DBEngExt,
  System.Rtti, System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.Components,
  Data.Bind.DBScope, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
  FMX.ListView, FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm9 = class(TForm)
    lbl1: TLabel;
    lsv1: TListView;
    con1: TFDConnection;
    qryLists: TFDQuery;
    bdr1: TBindSourceDB;
    bdl1: TBindingsList;
    tcf1: TLinkFillControlToField;
    lpfText: TLinkPropertyToField;
    qryInsert: TFDQuery;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form9: TForm9;

implementation

{$R *.fmx}

procedure TForm9.btn1Click(Sender: TObject);
begin
  qryInsert.ParamByName('id').AsInteger := 1;
  qryInsert.ParamByName('cur_datetime').AsDateTime := now;
  qryInsert.ParamByName('name').AsString := 'sample';
  qryInsert.ParamByName('size_cont').AsString := 'size_cont';
  qryInsert.ParamByName('qty').AsFloat := 10;
  qryInsert.ParamByName('est_price').AsFloat := 1234.5;
  qryInsert.ParamByName('qty_price').AsString := '10 x 1234.5';
  qryInsert.ParamByName('estimate').AsString := FormatFloat('#,##0.00', 10 * 1234.5); //the result is giving me 12 (the correct one is 12,345.00)
  qryInsert.ExecSQL;
  qryLists.Close;
  qryLists.Open();
end;

end.

FMX 文件:

object Form9: TForm9
  Left = 0
  Top = 0
  Caption = 'Form9'
  ClientHeight = 480
  ClientWidth = 308
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object lbl1: TLabel
    Align = Top
    StyledSettings = [Family, Style, FontColor]
    Size.Width = 308.000000000000000000
    Size.Height = 33.000000000000000000
    Size.PlatformDefault = False
    TextSettings.Font.Size = 14.000000000000000000
    TextSettings.HorzAlign = Center
    Text = '5'
    TabOrder = 0
  end
  object lsv1: TListView
    ItemAppearanceClassName = 'TImageListItemBottomDetailAppearance'
    ItemEditAppearanceClassName = 'TImageListItemBottomDetailShowCheckAppearance'
    HeaderAppearanceClassName = 'TListHeaderObjects'
    FooterAppearanceClassName = 'TListHeaderObjects'
    Align = Client
    Size.Width = 308.000000000000000000
    Size.Height = 407.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 1
  end
  object btn1: TButton
    Align = Bottom
    Position.Y = 440.000000000000000000
    Size.Width = 308.000000000000000000
    Size.Height = 40.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 7
    Text = 'btn1'
    OnClick = btn1Click
  end
  object con1: TFDConnection
    Params.Strings = (
      
        'Database=D:\My Project Files\5. my_projects_aws-rest\project_x_v' +
        '0\application\client\database\smartcart.s3db'
      'LockingMode=Normal'
      'DriverID=SQLite')
    Connected = True
    LoginPrompt = False
    Left = 72
    Top = 24
  end
  object qryLists: TFDQuery
    Active = True
    Connection = con1
    SQL.Strings = (
      'SELECT id, date_created, name, size_cont, qty_price, estimate'
      'FROM lists ORDER BY date_created DESC')
    Left = 112
    Top = 24
  end
  object bdr1: TBindSourceDB
    DataSet = qryLists
    ScopeMappings = <>
    Left = 152
    Top = 24
  end
  object bdl1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 20
    Top = 5
    object tcf1: TLinkFillControlToField
      Category = 'Quick Bindings'
      Control = lsv1
      Track = True
      FillDataSource = bdr1
      AutoFill = True
      FillExpressions = <
        item
          SourceMemberName = 'estimate'
          ControlMemberName = 'Detail'
        end>
      FillHeaderExpressions = <>
      FillBreakGroups = <>
    end
    object lpfText: TLinkPropertyToField
      Category = 'Quick Bindings'
      DataSource = bdr1
      FieldName = 'estimate'
      Component = lbl1
      ComponentProperty = 'Text'
    end
  end
  object qryInsert: TFDQuery
    Connection = con1
    SQL.Strings = (
      'INSERT INTO lists (id, date_created, name, size_cont, '
      '                   qty, est_price, qty_price, estimate) '
      'VALUES (:id, :cur_datetime, :name, :size_cont, '
      '        :qty, :est_price, :qty_price, :estimate);')
    Left = 192
    Top = 24
    ParamData = <
      item
        Name = 'ID'
        DataType = ftInteger
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'CUR_DATETIME'
        DataType = ftDateTime
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'NAME'
        DataType = ftString
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'SIZE_CONT'
        DataType = ftString
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'QTY'
        DataType = ftFloat
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'EST_PRICE'
        DataType = ftFloat
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'QTY_PRICE'
        DataType = ftString
        ParamType = ptInput
        Value = Null
      end
      item
        Name = 'ESTIMATE'
        DataType = ftFloat
        ParamType = ptInput
        Value = Null
      end>
  end
end

更新: TListView 属性截图

【问题讨论】:

  • 你为什么用AsString而不是AsFloat
  • 我认为 FormatFloat 是一个字符串。如果我将其更改为 AsFloat,则会收到此错误 [dcc32 Error] Unit9.pas(53): E2010 Incompatible types: 'Double' and 'string'
  • 你根本不需要 FormatFloat。删除它,然后使用AsFloat 将浮点值直接分配给参数,如qryInsert.ParamByName('estimate').AsFloat := 1234.5 * 10;
  • 没有。我是说您使用错误的参数值,我已经告诉您如何纠正该问题。现在,您正在添加与您在此处提出的问题无关的问题。如果您使用AsFloat 并直接分配值而不使用FormatFloat,那么您遇到的问题就会消失。格式化显示值是一个完全不同的问题。参数与向用户显示数据无关
  • 可能@KenWhite 试图说他回答了你的问题(他的回答:将值保存为数据库中的浮点数以避免 FormatFloat),你必须问另一个问题以获得副作用。这个问题类似于“使用 LiveBinding,我如何将格式化的浮点值从数据库转换为 TListView”。

标签: listview delphi firemonkey


【解决方案1】:

根据您的表单定义文件,您的参数定义为Datatype = ftFloat

item
  Name = 'ESTIMATE'
  DataType = ftFloat
  ParamType = ptInput
  Value = Null
end>

这意味着您根本不需要使用参数的AsString 分配值或使用FormatFloat 转换它,因为您可以直接将值分配为浮点值。

qryInsert.ParamByName('estimate').AsFloat := 10 * 1234.5;

这样做不会导致任何舍入错误,因为数据以正确的值存储。根本不进行四舍五入。

【讨论】:

  • 非常感谢。我将发布另一个与在用户界面级别以所需格式显示数字的问题有关的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多