java-tools / fixedformat4j

Automatically exported from code.google.com/p/fixedformat4j
0 stars 0 forks source link

@FixedFormatDecimal with more than 3 decimals truncates decimals #16

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

Create the following 2 files and run the test case.

DecimalRecord.java:

import java.math.BigDecimal;

import com.ancientprogramming.fixedformat4j.annotation.Align;
import com.ancientprogramming.fixedformat4j.annotation.Field;
import com.ancientprogramming.fixedformat4j.annotation.FixedFormatDecimal;
import com.ancientprogramming.fixedformat4j.annotation.Record;

@Record
public class DecimalRecord {

    private double doubleValue;
    private BigDecimal bigDecimalValue;

    public DecimalRecord(double doubleValue, BigDecimal bigDecimalValue) {
        this.doubleValue = doubleValue;
        this.bigDecimalValue = bigDecimalValue;
    }

    @Field(offset = 1, length=8, align=Align.RIGHT)
    @FixedFormatDecimal(decimals=4, useDecimalDelimiter=true)
    public double getDoubleValue() {
        return doubleValue;
    }

    @Field(offset = 9, length=8, align=Align.RIGHT)
    @FixedFormatDecimal(decimals = 4, useDecimalDelimiter=true)
    public BigDecimal getBigDecimalValue() {
        return bigDecimalValue;
    }

}

FixedFormatDecimalTest.java:

import static org.junit.Assert.assertEquals;

import java.math.BigDecimal;

import org.junit.Test;

import com.ancientprogramming.fixedformat4j.format.FixedFormatManager;
import com.ancientprogramming.fixedformat4j.format.impl.FixedFormatManagerImpl;

public class FixedFormatDecimalTest {

    @Test
    public void fixedFormatDoesntTrimLastDecimals() {

        String stringValue = "12.34567";        
        DecimalRecord record = new DecimalRecord(12.34567, new BigDecimal(stringValue));
        String expectedRecord = " 12.3457" + " 12.3457";
        FixedFormatManager fixedFormatManager = new FixedFormatManagerImpl();
        String formattedRecord = fixedFormatManager.export(record);
        assertEquals(expectedRecord, formattedRecord);

    }

}

What is the expected output? What do you see instead?
Expected:  12.3457 12.3457
Actual:  12.3460 12.3460

What version of the product are you using? On what Java version?
fixedformat4j-1.3.1.jar

Java on Mac:
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02-279-10M3065)
Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01-279, mixed mode)

Java on Windows (same problem):
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode)

Please provide any additional information below.

The problem seems to be that the first call in AbstractDecimalFormat.asString(T 
obj, FormatInstructions instructions):

    String rawString = obj != null ? FORMATTER.format(obj) : ZERO_STRING;

Returns a rawString that has been rounded to three decimals (12.346) and later 
in the method a trim to the specified number of decimals (4) is done, but by 
then the last decimal is already lost.

Looking at the junit test cases for fixedformat4j I notice that there doesn't 
seem to be any test cases that uses more than 3 decimals, so I added a couple 
to TestBigDecimalFormatter.java and TestDoubleFormatter.java that exposes the 
problem:

  public void testFormatBigDecimalWith4DecimalsKeepAllDecimalsNoDecimalDelimiter() {
    assertEquals("+00012345612", formatter.format(new BigDecimal(1234.5612), new FormatInstructions(12, Align.RIGHT, '0', null, null, new FixedFormatNumberData(Sign.PREPEND, DEFAULT_POSITIVE_SIGN, DEFAULT_NEGATIVE_SIGN), new FixedFormatDecimalData(4, false, '.'))));      
  }

  public void testFormatBigDecimalWith5DecimalsTo4DecimalsNoDecimalDelimiter() {
    assertEquals("+00012345612", formatter.format(new BigDecimal(1234.56121), new FormatInstructions(12, Align.RIGHT, '0', null, null, new FixedFormatNumberData(Sign.PREPEND, DEFAULT_POSITIVE_SIGN, DEFAULT_NEGATIVE_SIGN), new FixedFormatDecimalData(4, false, '.'))));
  }

  public void testFormatBigDecimalWith4DecimalsKeepAllDecimalsUseDecimalDelimiter () {
    assertEquals("+001234.5612", formatter.format(new BigDecimal(1234.5612), new FormatInstructions(12, Align.RIGHT, '0', null, null, new FixedFormatNumberData(Sign.PREPEND, DEFAULT_POSITIVE_SIGN, DEFAULT_NEGATIVE_SIGN), new FixedFormatDecimalData(4, true, '.'))));  
  }

  public void testFormatBigDecimalWith5DecimalsTo4DecimalsUseDecimalDelimiter () {
      assertEquals("+00123.4561", formatter.format(new BigDecimal(123.45612), new FormatInstructions(11, Align.RIGHT, '0', null, null, new FixedFormatNumberData(Sign.PREPEND, DEFAULT_POSITIVE_SIGN, DEFAULT_NEGATIVE_SIGN), new FixedFormatDecimalData(4, true, '.'))));  
  }

  public void testFormatDoubleWith4DecimalsKeepAllDecimals() {
    assertEquals("+001005055", formatter.format(new Double(100.5055), new FormatInstructions(10, Align.RIGHT, '0', null, null, new FixedFormatNumberData(Sign.PREPEND, DEFAULT_POSITIVE_SIGN, DEFAULT_NEGATIVE_SIGN), new FixedFormatDecimalData(4, false, '.'))));

  }

  public void testFormatDoubleWith5DecimalsTo4Decimals() {
    assertEquals("+001005556", formatter.format(new Double(100.55555), new FormatInstructions(10, Align.RIGHT, '0', null, null, new FixedFormatNumberData(Sign.PREPEND, DEFAULT_POSITIVE_SIGN, DEFAULT_NEGATIVE_SIGN), new FixedFormatDecimalData(4, false, '.'))));
  }

Original issue reported on code.google.com by magnus.neck on 9 Aug 2010 at 8:25

GoogleCodeExporter commented 9 years ago

Original comment by per.ole...@gmail.com on 14 Dec 2010 at 11:58

GoogleCodeExporter commented 9 years ago
Fixed by fix of issue #20.

Also added all your nice tests and they show up green now :-)

Original comment by per.ole...@gmail.com on 14 Dec 2010 at 3:11