Avatar billede borrisholt Novice
27. marts 2008 - 10:08 Der er 5 kommentarer og
1 løsning

Nu droppes 25 øren!. Hvordan får vi så afrundet ?

Hej

Her er så en generel løsning for hvordan man afrundet til nærmeste xx enhed .... Dette er ikke et spørgsmål men kun en generel information ...

unit AfrundU;

interface
uses
  SysUtils, Math;
type
  TRoundStruct = record
    NewMount: Double;
    Diff: Double;
  end;

  TAfrund = function(const Amount: Double): TRoundStruct;
  TCoinUnit = (cu1 = 1, cu2 = 2, cu5 = 5, cu10 = 10, cu25 = 25, cu50 = 50, //Små mønter
    cu100 = 100, cu200 = 200, cu500 = 500, cu10000 = 100000, cu20000 = 20000, //Store mønter
    cu50000 = 50000, cu100000 = 100000, cu200000 = 200000, cu500000 = 500000, cu1000000 = 1000000); //Sedler

function JBRoundFloat(Value: Extended; const NumberOfDecimals: Byte = 2): Extended;
function Afrund(const Amount: Double; const CoinUnit: TCoinUnit = cu25): Double;
function AfrundJB(const Amount: Double; const CoinUnit: TCoinUnit = cu25): TRoundStruct;
function FindRestVedAfrundning(const tal: Currency; const CoinUnit: TCoinUnit = cu25): Currency;

implementation

function JBRoundFloat(Value: Extended; const NumberOfDecimals: Byte = 2): Extended;
var
  Factor: Extended;
begin
  Factor := IntPower(10, NumberOfDecimals);

  if Frac(Value * Factor) >= 0.5 then
    Value := Value + 1 / (IntPower(10, NumberOfDecimals + 1));

  Result := StrToFloat(Format('%.*f', [CurrencyDecimals, Value]));
end;

function AfrundJB(const Amount: Double; const CoinUnit: TCoinUnit): TRoundStruct;
begin
  Result.NewMount := JBRoundFloat(Amount / Integer(CoinUnit)) * Integer(CoinUnit);
  Result.Diff := JBRoundFloat(Result.NewMount - Amount);
end;

function Afrund(const Amount: Double; const CoinUnit: TCoinUnit): Double;
begin
  Result := AfrundJB(Amount, CoinUnit).NewMount;
end;

function FindRestVedAfrundning(const tal: Currency; const CoinUnit: TCoinUnit): Currency;
begin
  Result := AfrundJB(Tal, CoinUnit).Diff;
end;
end.
Avatar billede nielle Nybegynder
27. marts 2008 - 10:25 #1
Måske skulle du skrive det som en artikel i stedet.

Placeret her vil den jo bare forsvinde fra "radaren" i løbet af de næste par dage. :^)
Avatar billede stone Forsker
27. marts 2008 - 13:23 #2
Tak borrisholt, det kan jeg godt bruge "S"
Avatar billede borrisholt Novice
27. marts 2008 - 17:10 #3
Hvis man foretrækker det som en klasse, eller i en c# version så kommer løsningen her :

uses
  SysUtils, Math;

type
  TRoundStruct = record
    NewMount: Double;
    Diff: Double;
  end;

  TCoinUnit = (cu1 = 1, cu2 = 2, cu5 = 5, cu10 = 10, cu25 = 25, cu50 = 50, //Små mønter
    cu100 = 100, cu200 = 200, cu500 = 500, cu10000 = 100000, cu20000 = 20000, //Store mønter
    cu50000 = 50000, cu100000 = 100000, cu200000 = 200000, cu500000 = 500000, cu1000000 = 1000000); //Sedler

  TAfrundning = class
  private
    FCoinUnit: TCoinUnit;
  protected
    class function AfrundJB(const Amount: Double; const CoinUnit: TCoinUnit = cu25): TRoundStruct;
  public
    class function JBRoundFloat(Value: Extended; const NumberOfDecimals: Byte = 2): Extended;
    class function Afrund(const Amount: Double; const CoinUnit: TCoinUnit = cu25): Double; overload;
    class function FindRestVedAfrundning(const Amount: Double; const CoinUnit: TCoinUnit = cu25): Currency; overload;

    function Afrund(const Amount: Double): Double; overload;
    function FindRestVedAfrundning(const Amount: Double): Currency; overload;

    constructor Create; overload;
    constructor Create(ACoinUnit: TCoinUnit); overload;

    property CoinUnit: TCoinUnit read FCoinUnit;
  end;

function JBRoundFloat(Value: Extended; const NumberOfDecimals: Byte = 2): Extended;

implementation

{ TAfrundning }

class function TAfrundning.Afrund(const Amount: Double; const CoinUnit: TCoinUnit): Double;
begin
  Result := AfrundJB(Amount, CoinUnit).NewMount;
end;

function TAfrundning.Afrund(const Amount: Double): Double;
begin
  Result := Afrund(Amount, FCoinUnit)
end;

class function TAfrundning.AfrundJB(const Amount: Double; const CoinUnit: TCoinUnit): TRoundStruct;
begin
  Result.NewMount := JBRoundFloat(Amount / Integer(CoinUnit)) * Integer(CoinUnit);
  Result.Diff := JBRoundFloat(Result.NewMount - Amount);
end;

constructor TAfrundning.Create(ACoinUnit: TCoinUnit);
begin
  inherited Create;
  FCoinUnit := ACoinUnit;
end;

function TAfrundning.FindRestVedAfrundning(const Amount: Double): Currency;
begin
  Result := FindRestVedAfrundning(Amount, FCoinUnit)
end;

constructor TAfrundning.Create;
begin
  inherited;
  FCoinUnit := cu25;
end;

class function TAfrundning.FindRestVedAfrundning(const Amount: Double; const CoinUnit: TCoinUnit): Currency;
begin
  Result := AfrundJB(Amount, CoinUnit).Diff;
end;

class function TAfrundning.JBRoundFloat(Value: Extended; const NumberOfDecimals: Byte): Extended;
var
  Factor: Extended;
begin
  Factor := IntPower(10, NumberOfDecimals);

  if Frac(Value * Factor) >= 0.5 then
    Value := Value + 1 / (IntPower(10, NumberOfDecimals + 1));

  Result := StrToFloat(Format('%.*f', [CurrencyDecimals, Value]));
end;

function JBRoundFloat(Value: Extended; const NumberOfDecimals: Byte = 2): Extended;
begin
  Result := TAfrundning.JBRoundFloat(Value, NumberOfDecimals);
end;


using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication4
{
    public struct RoundStruct
    {
        public double NewMount;
        public double Diff;
    }

    enum CoinUnit
    {
        cu1 = 1, cu2 = 2, cu5 = 5, cu10 = 10, cu25 = 25, cu50 = 50, //Små mønter
        cu100 = 100, cu200 = 200, cu500 = 500, cu10000 = 100000, cu20000 = 20000, //Store mønter
        cu50000 = 50000, cu100000 = 100000, cu200000 = 200000, cu500000 = 500000, cu1000000 = 1000000  //Sedler
    };


    class ClassAfrundning
    {

        internal CoinUnit FUnit = CoinUnit.cu25;

        public CoinUnit Unit
        {
            get
            {
                return FUnit;
            }
        }

        public ClassAfrundning(CoinUnit Unit)
            : base()
        {
            FUnit = Unit;
        }

        public ClassAfrundning()
            : base()
        {

        }

        protected static RoundStruct AfrundJB(double Amount, CoinUnit Unit)
        {
            RoundStruct Result;
            Result.NewMount = Math.Round(Amount / (int)Unit, 2) * (int)Unit;
            Result.Diff = Math.Round(Result.NewMount - Amount);
            return Result;
        }

        protected virtual RoundStruct AfrundJB(double Amount)
        {
            return AfrundJB(Amount, FUnit);
        }

        public static double Afrund(double Amount, CoinUnit Unit)
        {
            return AfrundJB(Amount, Unit).NewMount;
        }

        public double Afrund(double Amount)
        {
            return AfrundJB(Amount, Unit).NewMount;
        }

        public static double FindRestVedAfrundning(double Amount, CoinUnit Unit)
        {
            return AfrundJB(Amount, Unit).Diff;
        }

        public double FindRestVedAfrundning(double Amount)
        {
            return AfrundJB(Amount, Unit).Diff;
        }
    }
}


Jens B
Avatar billede arne_v Ekspert
29. marts 2008 - 04:06 #4
Øhm.

Nu har jeg kun kigget på C# koden, men:
- Math.Round brugt som i koden vil lave bankers rounding ikke 4/5 rounding som man bruger i Danmark
- man bør ikke bruge double til beløb, man bør bruge decimal i.s.f.
Avatar billede arne_v Ekspert
29. marts 2008 - 04:12 #5
Nu har jeg lige kigget på Delphi delen.

Hvad gør:

  if Frac(Value * Factor) >= 0.5 then
    Value := Value + 1 / (IntPower(10, NumberOfDecimals + 1));
  Result := StrToFloat(Format('%.*f', [CurrencyDecimals, Value]));

som:

  Result := Trunc(Value * Factor + 0.5) / Factor;

ikke gør ?
Avatar billede borrisholt Novice
02. oktober 2008 - 11:34 #6
Lukkes ... Oprydning ;)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester