Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #181: float32 accuracy issue #196

Merged
merged 6 commits into from
Jun 12, 2020

Conversation

willson-chen
Copy link
Contributor

@willson-chen willson-chen commented Jun 4, 2020

The issue accuracy is caused by casting from float32 to float64 when encoding, which leads to extra decimal appended to the original float. Transformation from float32 to string, and then float64 could avoid this issue.

@wongoo
Copy link
Contributor

wongoo commented Jun 4, 2020

a unit test is required for it

@codecov-commenter
Copy link

codecov-commenter commented Jun 4, 2020

Codecov Report

Merging #196 into master will increase coverage by 0.41%.
The diff coverage is 68.75%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #196      +/-   ##
==========================================
+ Coverage   66.01%   66.42%   +0.41%     
==========================================
  Files          22       22              
  Lines        2845     2850       +5     
==========================================
+ Hits         1878     1893      +15     
+ Misses        749      742       -7     
+ Partials      218      215       -3     
Impacted Files Coverage Δ
double.go 86.15% <66.66%> (-5.85%) ⬇️
encode.go 88.29% <100.00%> (ø)
decode.go 68.37% <0.00%> (+1.70%) ⬆️
string.go 57.91% <0.00%> (+2.54%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9ab1067...6eccb03. Read the comment docs.

encode.go Outdated Show resolved Hide resolved
@wongoo
Copy link
Contributor

wongoo commented Jun 4, 2020

suggest to add a new func encFloat32 to receive a float32 and encode it, the string converting would degrade performance

@willson-chen
Copy link
Contributor Author

I referenced dubbo-hessian-lite/PR#12 to create this patch.

Adding func encFloat32 is a good choice. And then we should encode the float32 directly indead of casting it to float64. BTW, casting causes the accuracy issue. But I am not sure if it will introduce any compatibility issues.

double     ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0   # 64-bit float
           ::= x5b                   # 0.0
           ::= x5c                   # 1.0
           ::= x5d b0                # byte cast to double
                                     #  (-128.0 to 127.0)
           ::= x5e b1 b0             # short cast to double
           ::= x5f b3 b2 b1 b0       # 32-bit float cast to double

@wongoo
Copy link
Contributor

wongoo commented Jun 4, 2020

currently hessian2 encoding all float as 64-bit float, while decoding support multiple cases.
it's worth to do effort to let the encoding follow the protocol.

@AlexStocks
Copy link
Contributor

currently hessian2 encoding all float as 64-bit float, while decoding support multiple cases.
it's worth to do effort to let the encoding follow the protocol.

we can add comment here. In my opinion, we should keep pace with dubbo-hessian-lite.

double_test.go Outdated Show resolved Hide resolved
@wongoo
Copy link
Contributor

wongoo commented Jun 5, 2020

pls check whether dubbo-hessian-lite support 32-bit format x5f b3 b2 b1 b0 # 32-bit float cast to double

@willson-chen
Copy link
Contributor Author

pls check whether dubbo-hessian-lite support 32-bit format x5f b3 b2 b1 b0 # 32-bit float cast to double

Hi, here is the implement of float32 encode in dubbo-hessian-lite. As we can see, dubbo-hessian-lite cast float to double. So I don't think it supports the 32-bit format.

@wongoo
Copy link
Contributor

wongoo commented Jun 5, 2020

@willson-chen
Copy link
Contributor Author

@wongoo yeah, you are right. I had a careful check the code block, and foud dubbo-hessian-lite both support hessian and hessian2. hessian has only double ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0 format when encoding float and double.

In fact, dubbo-hessian-lite encode the number depending the value, but not the type, float(32-bit in java) or double(64-bit in java). All the float would be transform to double, and when the value is less then 3 digits after the decimal point, the number will be encoded in x5f b3 b2 b1 b0 format.

So what should we do?

  • Follow dubbo-hessian-lite, we should add the value judgement and deside which format to encode in func encFloat of double.go.
  • Encode exactly depend on the type, we should add func encFloat32.

@wongoo
Copy link
Contributor

wongoo commented Jun 5, 2020

Encode exactly depend on the type, we should add func encFloat32.

my opinion is adding a new func for float32.

- Call encFloat32 to encode float32 while encoding
- Add unit test case to test float32 encoding
@willson-chen willson-chen requested a review from wongoo June 9, 2020 02:33
Copy link
Contributor

@wongoo wongoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls add unit test for math.MaxFloat32、math.MaxFloat32-1、math.MaxFloat32+1、math.MaxFloat64、math.MaxFloat64-1

double.go Outdated Show resolved Hide resolved
@wongoo
Copy link
Contributor

wongoo commented Jun 10, 2020

The command "go fmt && [[ -z git status -s ]]" exited with 1.

pls format the code

@willson-chen
Copy link
Contributor Author

pls add unit test for math.MaxFloat32、math.MaxFloat32-1、math.MaxFloat32+1、math.MaxFloat64、math.MaxFloat64-1

Fair enough. But I need some time to adjust the test case.

pls format the code

done

Copy link
Contributor

@wongoo wongoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@wongoo wongoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wongoo wongoo requested a review from fangyincheng June 11, 2020 01:03
Copy link
Member

@zonghaishang zonghaishang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hessian2规范 float就是64位的,hessian go不应该用float32去表示它,因为可能溢出不能完全解决问题。

我的建议:

  1. 针对hessian库支持,应该用float64去处理,不应该用float32,并且不应先转string,因为float是基础类型
  2. 应该在readme告知开发者应该使用float64

Hessian2 float is 64-bit, and Hessian Go should not be represented by float32 because overflow may not solve the problem completely.

my advice:

  1. Hessian Go USES Float64 encoding and decoding instead of converting a String first
  2. The user should be explicitly informed in the ReadME of Hessian Go that instead of using Float32, it should be treated with Float64.

Copy link
Contributor

@fangyincheng fangyincheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wongoo wongoo merged commit 4eb650b into apache:master Jun 12, 2020
@willson-chen willson-chen deleted the fix_float32_accuracy branch June 12, 2020 07:26
wongoo added a commit that referenced this pull request Jun 15, 2020
* add license checker (#175)

* add release note for v1.5.0 (#178)

Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>

* Imp: cache in reflection (#179)

* benchmark result

* use cache in findField

* encode benchmark

* call field() once

* remove version

* fix import sync

* cache in registerPOJO

* add json bench result

* prune unneccessary rtype.Field(index)

* cache comment

* rename cache

* switch to if

* remove return value name

* findFieldWithCache

* remove if check when fieldStruct is nil

Co-authored-by: 望哥 <gelnyang@163.com>

* update dependency

* rename serialize arg name

* Create .asf.yaml

* 优化hessian解码string性能,提升54%

* optimize code.

* optimize code.

* fix code review.

* optimize codes.

* optimize cods.

* optimize code.

* update license

* go.sum

* ci go version

* testify -> 1.4.0

* testcase

* travis.yml

* decode value before reflect find

* setvalue

* decode nilPtr to nilPtr

* fix get attachment lost nil key

* manually import package

* add ToMapStringString unit test

* rename test function name with issue

* setmap

* support for decode emoji.

* refactor code

* add unit test.

* add unit tests.

* refactor tests.

* Update travis/main.sh (#200)

- Remove duplicate key 'webhooks'
- Key 'matrix' is an alias for `jobs`, using `jobs`
- Specify the os and dist explicitly

* Mod: modify

* Code format (#199)

* .gitignore

* code clean

* code clean

* remove length check

* Fix: comments

* Fix: format package

* Fix #181: float32 accuracy issue (#196)

* Fix #181: float32 accuracy issue

* Fix go fmt failure

* Add the unit test case for Issue181

* Add encFloat32 in double.go to encode float32 type

- Call encFloat32 to encode float32 while encoding
- Add unit test case to test float32 encoding

* Improve encFloat32 of double.go

* Fix git fmt failure

* add release note for v1.6.0 (#202)

* add release note for v1.5.1

* add release note for v1.5.1

* add notice

* update notice

* =fix release note for v1.6.0

Co-authored-by: Joe Zou <joezou@apache.org>
Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>
Co-authored-by: huiren <zhrlnt@gmail.com>
Co-authored-by: Huang YunKun <htynkn@gmail.com>
Co-authored-by: zonghaishang <yiji@apache.org>
Co-authored-by: fangyincheng <fangyc666@gmail.com>
Co-authored-by: champly <champly@outlook.com>
Co-authored-by: wilson chen <willson.chenwx@gmail.com>
Co-authored-by: fangyincheng <fangyincheng@sina.com>
Co-authored-by: gaoxinge <gaoxx5@gmail.com>
wongoo added a commit that referenced this pull request Jun 23, 2020
* add license checker (#175)

* add release note for v1.5.0 (#178)

Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>

* Imp: cache in reflection (#179)

* benchmark result

* use cache in findField

* encode benchmark

* call field() once

* remove version

* fix import sync

* cache in registerPOJO

* add json bench result

* prune unneccessary rtype.Field(index)

* cache comment

* rename cache

* switch to if

* remove return value name

* findFieldWithCache

* remove if check when fieldStruct is nil

Co-authored-by: 望哥 <gelnyang@163.com>

* update dependency

* rename serialize arg name

* Create .asf.yaml

* 优化hessian解码string性能,提升54%

* optimize code.

* optimize code.

* fix code review.

* optimize codes.

* optimize cods.

* optimize code.

* update license

* go.sum

* ci go version

* testify -> 1.4.0

* testcase

* travis.yml

* decode value before reflect find

* setvalue

* decode nilPtr to nilPtr

* fix get attachment lost nil key

* manually import package

* add ToMapStringString unit test

* rename test function name with issue

* setmap

* support for decode emoji.

* refactor code

* add unit test.

* add unit tests.

* refactor tests.

* Update travis/main.sh (#200)

- Remove duplicate key 'webhooks'
- Key 'matrix' is an alias for `jobs`, using `jobs`
- Specify the os and dist explicitly

* Mod: modify

* Code format (#199)

* .gitignore

* code clean

* code clean

* remove length check

* Fix: comments

* Fix: format package

* Fix #181: float32 accuracy issue (#196)

* Fix #181: float32 accuracy issue

* Fix go fmt failure

* Add the unit test case for Issue181

* Add encFloat32 in double.go to encode float32 type

- Call encFloat32 to encode float32 while encoding
- Add unit test case to test float32 encoding

* Improve encFloat32 of double.go

* Fix git fmt failure

* add release note for v1.6.0 (#202)

* add release note for v1.5.1

* add release note for v1.5.1

* add notice

* update notice

* =fix release note for v1.6.0

* Fix: eunm encode in request get error (#203)

* fix bug: eunm encode in request get error

* fix mod

* add ut

* remove go.mod 1.13 to fix the ci

Co-authored-by: Joe Zou <joezou@apache.org>
Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>
Co-authored-by: huiren <zhrlnt@gmail.com>
Co-authored-by: Huang YunKun <htynkn@gmail.com>
Co-authored-by: zonghaishang <yiji@apache.org>
Co-authored-by: fangyincheng <fangyc666@gmail.com>
Co-authored-by: champly <champly@outlook.com>
Co-authored-by: wilson chen <willson.chenwx@gmail.com>
Co-authored-by: fangyincheng <fangyincheng@sina.com>
Co-authored-by: gaoxinge <gaoxx5@gmail.com>
Co-authored-by: panty <pantianying@gmail.com>
zhaoyunxing92 pushed a commit that referenced this pull request Sep 4, 2021
* Fix #181: float32 accuracy issue

* Fix go fmt failure

* Add the unit test case for Issue181

* Add encFloat32 in double.go to encode float32 type

- Call encFloat32 to encode float32 while encoding
- Add unit test case to test float32 encoding

* Improve encFloat32 of double.go

* Fix git fmt failure
zhaoyunxing92 pushed a commit that referenced this pull request Sep 4, 2021
* add license checker (#175)

* add release note for v1.5.0 (#178)

Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>

* Imp: cache in reflection (#179)

* benchmark result

* use cache in findField

* encode benchmark

* call field() once

* remove version

* fix import sync

* cache in registerPOJO

* add json bench result

* prune unneccessary rtype.Field(index)

* cache comment

* rename cache

* switch to if

* remove return value name

* findFieldWithCache

* remove if check when fieldStruct is nil

Co-authored-by: 望哥 <gelnyang@163.com>

* update dependency

* rename serialize arg name

* Create .asf.yaml

* 优化hessian解码string性能,提升54%

* optimize code.

* optimize code.

* fix code review.

* optimize codes.

* optimize cods.

* optimize code.

* update license

* go.sum

* ci go version

* testify -> 1.4.0

* testcase

* travis.yml

* decode value before reflect find

* setvalue

* decode nilPtr to nilPtr

* fix get attachment lost nil key

* manually import package

* add ToMapStringString unit test

* rename test function name with issue

* setmap

* support for decode emoji.

* refactor code

* add unit test.

* add unit tests.

* refactor tests.

* Update travis/main.sh (#200)

- Remove duplicate key 'webhooks'
- Key 'matrix' is an alias for `jobs`, using `jobs`
- Specify the os and dist explicitly

* Mod: modify

* Code format (#199)

* .gitignore

* code clean

* code clean

* remove length check

* Fix: comments

* Fix: format package

* Fix #181: float32 accuracy issue (#196)

* Fix #181: float32 accuracy issue

* Fix go fmt failure

* Add the unit test case for Issue181

* Add encFloat32 in double.go to encode float32 type

- Call encFloat32 to encode float32 while encoding
- Add unit test case to test float32 encoding

* Improve encFloat32 of double.go

* Fix git fmt failure

* add release note for v1.6.0 (#202)

* add release note for v1.5.1

* add release note for v1.5.1

* add notice

* update notice

* =fix release note for v1.6.0

Co-authored-by: Joe Zou <joezou@apache.org>
Co-authored-by: Xin.Zh <dragoncharlie@foxmail.com>
Co-authored-by: huiren <zhrlnt@gmail.com>
Co-authored-by: Huang YunKun <htynkn@gmail.com>
Co-authored-by: zonghaishang <yiji@apache.org>
Co-authored-by: fangyincheng <fangyc666@gmail.com>
Co-authored-by: champly <champly@outlook.com>
Co-authored-by: wilson chen <willson.chenwx@gmail.com>
Co-authored-by: fangyincheng <fangyincheng@sina.com>
Co-authored-by: gaoxinge <gaoxx5@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants