TheDataShed / xlsxreader

A low-memory high performance library for reading data from an xlsx file
https://godoc.org/github.com/TheDataShed/xlsxreader
MIT License
74 stars 21 forks source link

Floating point data rounding error #55

Closed arun-suryan closed 6 months ago

arun-suryan commented 1 year ago

Here is the code that I have written to read the attached file:

package main

import (
    "bytes"
    "encoding/csv"
    "fmt"
    "log"

    "github.com/thedatashed/xlsxreader"
)

// copy of https://godoc.org/github.com/tealeg/xlsx#ColLettersToIndex
// column is read from the right to left, for each char, res += (n+char-A)*26pow(i) (0<= i <=len(col)-1).
func columnIndex(col string) int {
    sum, mul, n := 0, 1, 0
    for i := len(col) - 1; i >= 0; i, mul, n = i-1, mul*26, 1 {
        c := col[i]
        switch {
        case c >= 'A' && c <= 'Z':
            n += int(c - 'A')
        case c >= 'a' && c <= 'z':
            n += int(c - 'a')
        }
        sum += n * mul
    }
    return sum
}

func getColCount(f *xlsxreader.XlsxFileCloser) int {
    row := <-f.ReadRows(f.Sheets[0])
    if row.Error != nil {
        return 0
    }
    return columnIndex(row.Cells[len(row.Cells)-1].Column) + 1
}

func main() {
    var result []string
    // Create an instance of the reader by opening a target file
    xl, _ := xlsxreader.OpenFile("./file1.xlsx")

    // Ensure the file reader is closed once utilised
    defer xl.Close()
    numColumns := getColCount(xl)
    for row := range xl.ReadRows(xl.Sheets[0]) {
        if row.Error != nil {
            continue
        }
        csvRow := make([]string, numColumns)
        data := make([][]string, 0)
        for _, curCell := range row.Cells {
            colIndex := columnIndex(curCell.Column)
            if colIndex < numColumns {
                csvRow[colIndex] = curCell.Value
            }
        }
        data = append(data, csvRow)
        buf := new(bytes.Buffer)
        w := csv.NewWriter(buf)
        err := w.WriteAll(data)
        if err != nil {
            panic(err)
        }
        if err := w.Error(); err != nil {
            log.Fatalln("error writing csv:", err)
        }
        csvString := buf.String()[:len(buf.String())-1]
        result = append(result, csvString)
    }
    fmt.Println(result)
}

However, When the data from the second row of the L column i.e. the value of the Facebook score is read then it's printed as 4.4000000000000004 instead of 4.4. Why is this rounding error coming in the case of some float-type data?

File_Attached_Here

KingMichaelPark commented 6 months ago

reverted this PR as the value actually is the value you report in this issue so it's on you to round it.

https://github.com/TheDataShed/xlsxreader/issues/59