diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas index 866daa12a..3faeb94b9 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas +++ b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas @@ -1741,7 +1741,7 @@ begin 'Token tNUM (Number)'); numBytes := 8; Move(FBuffer[FBufferIndex], dbl, numBytes); - ShowInRow(FCurrRow, FBufferIndex, numBytes, FloatToStr(dbl), + ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('%g', [dbl]), //FloatToStr(dbl), 'IEEE 754 floating-point value'); end; $20, $40, $60: @@ -2565,7 +2565,7 @@ begin // Offset 6: Double value numBytes := 8; Move(FBuffer[FBufferIndex], dbl, numBytes); - ShowInRow(FCurrRow, FBufferIndex, numBytes, FloatToStr(dbl), + ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('%g', [dbl]), //FloatToStr(dbl), 'IEEE 764 floating-point value'); end; diff --git a/components/fpspreadsheet/tests/formulatests.pas b/components/fpspreadsheet/tests/formulatests.pas index 6404351c1..9fefbda07 100644 --- a/components/fpspreadsheet/tests/formulatests.pas +++ b/components/fpspreadsheet/tests/formulatests.pas @@ -142,6 +142,7 @@ end; procedure TSpreadWriteReadFormulaTests.TestCalcRPNFormulas(AFormat: TsSpreadsheetFormat); const SHEET = 'Sheet1'; + STATS_NUMBERS: Array[0..4] of Double = (1.0, 1.1, 1.2, 0.9, 0.8); var MyWorksheet: TsWorksheet; MyWorkbook: TsWorkbook; @@ -156,8 +157,15 @@ var t: TTime; hr,min,sec,msec: Word; ErrorMargin: double; + k: Integer; + { When comparing soll and formula values we must make sure that the soll + values are calculated from double precision numbers, they are used in + the formula calculation as well. The next variables, along with STATS_NUMBERS + above, hold the arguments for the direction function calls. } + number: Double; + numberArray: array[0..4] of Double; begin - ErrorMargin:=1.44E-7; + ErrorMargin:=0; //1.44E-7; //1.44E-7 for SUMSQ formula //6.0E-8 for SUM formula //4.8E-8 for MAX formula @@ -208,6 +216,19 @@ begin CheckEquals(ord(expected.ArgumentType), ord(actual.ArgumentType), 'Test read calculated formula data type mismatch, formula "' + formula + '", cell '+CellNotation(MyWorkSheet,Row,1)); + + // The now function result is volatile, i.e. changes continuously. The + // time for the soll value was created such that we can expect to have + // the file value in the same second. Therefore we neglect the milliseconds. + if formula = '=NOW()' then begin + // Round soll value to seconds + DecodeTime(expected.NumberValue, hr,min,sec,msec); + expected.NumberValue := EncodeTime(hr, min, sec, 0); + // Round formula value to seconds + DecodeTime(actual.NumberValue, hr,min,sec,msec); + actual.NumberValue := EncodeTime(hr,min,sec,0); + end; + case actual.ArgumentType of atBool: CheckEquals(BoolToStr(expected.BoolValue), BoolToStr(actual.BoolValue), diff --git a/components/fpspreadsheet/tests/spreadtestgui.lpi b/components/fpspreadsheet/tests/spreadtestgui.lpi index ece61fcfa..da304374f 100644 --- a/components/fpspreadsheet/tests/spreadtestgui.lpi +++ b/components/fpspreadsheet/tests/spreadtestgui.lpi @@ -99,7 +99,6 @@ - @@ -109,7 +108,6 @@ - @@ -118,7 +116,6 @@ - @@ -131,6 +128,7 @@ + diff --git a/components/fpspreadsheet/tests/testcases_calcrpnformula.inc b/components/fpspreadsheet/tests/testcases_calcrpnformula.inc index 718d1c3be..a21c0aa9e 100644 --- a/components/fpspreadsheet/tests/testcases_calcrpnformula.inc +++ b/components/fpspreadsheet/tests/testcases_calcrpnformula.inc @@ -569,12 +569,15 @@ // ARCCOS - valid result inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=acos(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekACOS, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(arccos(0.1)); + sollValues[Row] := CreateNumberArg(arccos(number)); + // Don't explicitly use the constant here because this will be "extended" + // which is slightly different from the double value used in the formula // ACOS - error result (arccos is not defined outside the interval [-1..1] inc(Row); @@ -587,12 +590,13 @@ // ARCCOSH - valid result inc(Row); + number := 1.1; MyWorksheet.WriteUTF8Text(Row, 0, '=acosh(1.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( - RPNNumber(1.1, + RPNNumber(number, RPNFunc(fekACOSH, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(arccosh(1.1)); + sollValues[Row] := CreateNumberArg(arccosh(number)); // ACOSH - error result (arccos is not defined below 1 inc(Row); @@ -605,12 +609,13 @@ // ASIN inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=asin(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekASIN, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(arcsin(0.1)); + sollValues[Row] := CreateNumberArg(arcsin(number)); // ASIN - error result (arcsin is not defined outside the interval [-1..1] inc(Row); @@ -623,30 +628,33 @@ // ARCSINH inc(Row); + number := 1.1; MyWorksheet.WriteUTF8Text(Row, 0, '=asinh(1.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(1.1, RPNFunc(fekASINH, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(arcsinh(1.1)); + sollValues[Row] := CreateNumberArg(arcsinh(number)); // ATAN inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=atan(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekATAN, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(arctan(0.1)); + sollValues[Row] := CreateNumberArg(arctan(number)); // ATANH - valid result inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=atanh(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekATANH, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(arctanh(0.1)); + sollValues[Row] := CreateNumberArg(arctanh(number)); // ATANH - error result (arctan is only defined within ]-1,1[ inc(Row); @@ -659,21 +667,23 @@ // COS inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=cos(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekCOS, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(cos(0.1)); + sollValues[Row] := CreateNumberArg(cos(number)); // COSH inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=cosh(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekCOSH, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(cosh(0.1)); + sollValues[Row] := CreateNumberArg(cosh(number)); // DEGREES inc(Row); @@ -686,12 +696,13 @@ // EXP inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=exp(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekEXP, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(exp(0.1)); + sollValues[Row] := CreateNumberArg(exp(number)); // INT (positive argument) inc(Row); @@ -713,12 +724,13 @@ // LN - valid result inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=ln(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekLN, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(ln(0.1)); + sollValues[Row] := CreateNumberArg(ln(number)); // LN - error due to argument = 0 inc(Row); @@ -740,12 +752,13 @@ // LOG10 - valid result inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=log10(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekLOG10, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(log10(0.1)); + sollValues[Row] := CreateNumberArg(log10(number)); // LOG10 - error due to argument = 0 inc(Row); @@ -767,13 +780,14 @@ // LOG - valid result (2 arguments) inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=log(0.1, 2)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNNumber(2, RPNFunc(fekLOG, 2, nil))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(logn(2, 0.1)); + sollValues[Row] := CreateNumberArg(logn(2, number)); // LOG - valid result (2 arguments, base missing) inc(Row); @@ -787,12 +801,13 @@ // LOG - valid result (1 argument) inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=log(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekLOG, 1, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(logn(10, 0.1)); + sollValues[Row] := CreateNumberArg(logn(10, number)); // LOG - negative base inc(Row); @@ -883,12 +898,13 @@ // SIN inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=sin(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekSIN, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(sin(0.1)); + sollValues[Row] := CreateNumberArg(sin(number)); // SIN of cell value inc(Row); @@ -901,12 +917,13 @@ // SINH inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=sinh(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekSINH, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(sinh(0.1)); + sollValues[Row] := CreateNumberArg(sinh(number)); // SINH of cell value inc(Row); @@ -919,12 +936,13 @@ // SQRT - valid result inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=sqrt(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekSQRT, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(sqrt(0.1)); + sollValues[Row] := CreateNumberArg(sqrt(number)); // SQRT - error (negative argument) inc(Row); @@ -946,12 +964,13 @@ // TAN - valid result inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=tan(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekTAN, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(tan(0.1)); + sollValues[Row] := CreateNumberArg(tan(number)); // TAN - error (argument = pi/2) // This test is omitted because it is difficult to exactly hit pi/2. @@ -967,12 +986,13 @@ // TANH inc(Row); + number := 0.1; MyWorksheet.WriteUTF8Text(Row, 0, '=tanh(0.1)'); MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula( RPNNumber(0.1, RPNFunc(fekTANH, nil)))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(tanh(0.1)); + sollValues[Row] := CreateNumberArg(tanh(number)); // TANH of cell value inc(Row); @@ -1222,8 +1242,11 @@ RPNNumber(0.8, RPNFunc(fekAVEDEV, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(mean([0.0, 0.1, 0.2, 0.1, 0.2])); - // these values are the absolute deviations from mean (1.0) + number := mean(STATS_NUMBERS); + for k := 0 to High(STATS_NUMBERS) do numberArray[k] := abs(STATS_NUMBERS[k] - number); + // these values are the absolute deviations from mean (1.0) + sollValues[Row] := CreateNumberArg(mean(numberArray)); + // AVERAGE inc(Row); MyWorksheet.WriteUTF8Text(Row, 0, '=AVERAGE(1, 1.1, 1.2, 0.9, 0.8)'); @@ -1235,7 +1258,7 @@ RPNNumber(0.8, RPNFunc(fekAVERAGE, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(mean([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(mean(STATS_NUMBERS)); // AVERAGE of cell block inc(Row); @@ -1392,7 +1415,7 @@ RPNNumber(0.8, RPNFunc(fekMAX, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(MaxValue([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(MaxValue(STATS_NUMBERS)); // MAX of cell range (no empty cells) inc(Row); @@ -1423,7 +1446,7 @@ RPNNumber(0.8, RPNFunc(fekMIN, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(MinValue([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(MinValue(STATS_NUMBERS)); // PRODUCT inc(Row); @@ -1436,7 +1459,7 @@ RPNNumber(0.8, RPNFunc(fekPRODUCT, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(1.0*1.1*1.2*0.9*0.8); + sollValues[Row] := CreateNumberArg(STATS_NUMBERS[0]*STATS_NUMBERS[1]*STATS_NUMBERS[2]*STATS_NUMBERS[3]*STATS_NUMBERS[4]); // STDEV inc(Row); @@ -1449,7 +1472,7 @@ RPNNumber(0.8, RPNFunc(fekSTDEV, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(StdDev([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(StdDev(STATS_NUMBERS)); // STDEVP inc(Row); @@ -1462,7 +1485,7 @@ RPNNumber(0.8, RPNFunc(fekSTDEVP, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(PopnStdDev([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(PopnStdDev(STATS_NUMBERS)); // SUM inc(Row); @@ -1475,7 +1498,7 @@ RPNNumber(0.8, RPNFunc(fekSUM, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(Sum([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(Sum(STATS_NUMBERS)); if AFormat <> sfExcel2 then begin // SUMSQ @@ -1489,7 +1512,7 @@ RPNNumber(0.8, RPNFunc(fekSUMSQ, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(SumOfSquares([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(SumOfSquares(STATS_NUMBERS)); // SUMIF inc(Row); @@ -1558,7 +1581,7 @@ RPNNumber(0.8, RPNFunc(fekVAR, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(Variance([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(Variance(STATS_NUMBERS)); // VARP inc(Row); @@ -1571,7 +1594,7 @@ RPNNumber(0.8, RPNFunc(fekVARP, 5, nil)))))))); SetLength(sollValues, Row+1); - sollValues[Row] := CreateNumberArg(PopnVariance([1.0, 1.1, 1.2, 0.9, 0.8])); + sollValues[Row] := CreateNumberArg(PopnVariance(STATS_NUMBERS)); {------------------------------------------------------------------------------}