-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
expression: round function for int should use round half up rule #27403
Open
feitian124
wants to merge
13
commits into
pingcap:master
Choose a base branch
from
feitian124:issue-26993-new
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+72
−62
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
f724e87
add tests
feitian124 9d67a06
add RoundInt
feitian124 774878f
migrate types/helper_test.go to testify
feitian124 09dce5c
remove old roundfloat function
feitian124 d9f7037
add TestRoundInt
feitian124 d0f31ee
update comments
feitian124 53f0135
rename Round to RoundFloat
feitian124 b294341
int use RoundInt
feitian124 4c0e120
fix ci issue: fmt error
feitian124 dd67250
删掉可能导致block的测试用例
feitian124 0f088e6
use power instead of for loop
feitian124 39c1e99
Merge branch 'master' into issue-26993-new
tisonkun 9593daa
add test case for avoid float calc in int round
feitian124 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,31 +23,35 @@ import ( | |
"github.com/pingcap/errors" | ||
) | ||
|
||
// RoundFloat rounds float val to the nearest even integer value with float64 format, like MySQL Round function. | ||
// RoundFloat uses default rounding mode, see https://dev.mysql.com/doc/refman/5.7/en/precision-math-rounding.html | ||
// so rounding use "round to nearest even". | ||
// e.g, 1.5 -> 2, -1.5 -> -2. | ||
func RoundFloat(f float64) float64 { | ||
return math.RoundToEven(f) | ||
} | ||
|
||
// Round rounds the argument f to dec decimal places. | ||
// RoundFloat rounds the argument f to dec decimal places using "round to nearest even" rule. | ||
// dec defaults to 0 if not specified. dec can be negative | ||
// to cause dec digits left of the decimal point of the | ||
// value f to become zero. | ||
func Round(f float64, dec int) float64 { | ||
// see https://dev.mysql.com/doc/refman/5.7/en/precision-math-rounding.html | ||
func RoundFloat(f float64, dec int) float64 { | ||
shift := math.Pow10(dec) | ||
tmp := f * shift | ||
if math.IsInf(tmp, 0) { | ||
return f | ||
} | ||
result := RoundFloat(tmp) / shift | ||
result := math.RoundToEven(tmp) / shift | ||
if math.IsNaN(result) { | ||
return 0 | ||
} | ||
return result | ||
} | ||
|
||
// RoundInt rounds the argument i to dec decimal places using "round half up" rule. | ||
// dec defaults to 0 if not specified. dec can be negative | ||
func RoundInt(i int64, dec int) int64 { | ||
// is itself when dec >= 0 | ||
if dec >= 0 { | ||
return i | ||
} | ||
|
||
shift := math.Pow10(-dec) | ||
intPart := math.Round(float64(i) / shift) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a test case.
We should avoid float calc in int round. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added and failed, will fix later |
||
return int64(intPart) * int64(shift) | ||
} | ||
|
||
// Truncate truncates the argument f to dec decimal places. | ||
// dec defaults to 0 if not specified. dec can be negative | ||
// to cause dec digits left of the decimal point of the | ||
|
@@ -80,7 +84,7 @@ func TruncateFloat(f float64, flen int, decimal int) (float64, error) { | |
maxF := GetMaxFloat(flen, decimal) | ||
|
||
if !math.IsInf(f, 0) { | ||
f = Round(f, decimal) | ||
f = RoundFloat(f, decimal) | ||
} | ||
|
||
var err error | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider unsigned int range and overflow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for suggestion, i will check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i found both
mysql 8
andtidb v5.1.1
have above result,and
1234567890123456789012345678901234567890
is clearly much larger thanmath.MaxInt64
,so it cloud not be the param or return value of
builtinRoundWithFracIntSig.evalInt
,i believe above case and unsigned int should have processed in some other place,
so i will not process these case in
roundInt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so.
select round(1234567890123456789012345678901234567890, -30); This case is decimal round, not int.
We can create a table with bigint field and insert
-9223372036854775808
, then round it should throw the error.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can try to port mysql's logic https://github.com/mysql/mysql-server/blob/beb865a960b9a8a16cf999c323e46c5b0c67f21f/sql/item_func.cc#L3413