-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[Bug]: Inconsistent floating point behaviour changed between msbuild 16 and 17 #10105
Comments
@rainersigwald, @baronfel What would be the best strategy here? From engineering point of view, I would prefer to have everything invariant, but it could be a break change for some customers :| Other option is to revert the change and be dependent on current active culture. |
As for this excerpt from my analysis, regarding the inconsistency:
I now think that this inconsistency is what #9874 was about. It was resolved in 17.11. Back in May when we started getting 17.8 I summarised and worked around the issue like this: <!--Calculation of AllieraBuildSeconds. Seconds since midnight divided by two. -->
<PropertyGroup>
<!-- On msbuild 16 it worked to have separate properties like this, even with Swedish formatting
putting a decimal comma in TotalSeconds. On msbuild 17 (17.8) it will instead parse that back
as a thousands separator, producing a much too large value. Putting it all in a single expression works.
See msbuild issues #8710 and #10105. Possibly #9874 fixes it in 17.11 (changewave 17.12) by always using a decimal point? -->
<!-- <TotalSeconds>$([System.DateTime]::UtcNow.Subtract($([System.DateTime]::UtcNow.Date)).TotalSeconds)</TotalSeconds> -->
<!-- <AllieraBuildSeconds>$([System.Math]::Round($([MSBuild]::Divide($(TotalSeconds), 2))))</AllieraBuildSeconds> -->
<AllieraBuildSeconds>$([System.Math]::Round($([MSBuild]::Divide($([System.DateTime]::UtcNow.Subtract($([System.DateTime]::UtcNow.Date)).TotalSeconds), 2))))</AllieraBuildSeconds>
</PropertyGroup> And now, when some developers have moved to 17.11 we got a similar error in a different, but related code block, that I handled and described in this way just last week: <!--Calculation of AllieraBuildDays. Days passed since the introduction of the current versioning schema. -->
<PropertyGroup>
<!-- The following two lines fail from msbuils 17.11 likely due to msbuild change #9874. Before this change,
TotalDays would be coerced to string using decimal *comma* in Swedish locale, and ToDouble() would parse
that as expected using the same locale. Starting in 17.11 (changewave 17.12), msbuild will always use
a decimal point when converting to string, which .Net ToDouble() will not accept. We could fix for 17.11 by
just removing the ToDouble(), but then on 17.10 and earlier there will still be a decimal comma and
msbuild built-in coercion back to double will interpret it as a thousands separator. -->
<!-- <TotalDays>$([System.DateTime]::UtcNow.Subtract($([System.DateTime]::Parse("2020-01-01"))).TotalDays)</TotalDays> -->
<!-- <AllieraBuildDays>$([System.Math]::Floor($([System.Convert]::ToDouble($(TotalDays)))))</AllieraBuildDays> -->
<AllieraBuildDays>$([System.Math]::Floor($([System.DateTime]::UtcNow.Subtract($([System.DateTime]::Parse("2020-01-01"))).TotalDays)))</AllieraBuildDays>
</PropertyGroup> So at the moment I'm thinking that
The very long expressions are a bit difficult to read but I suppose they could be simplified after enough time has passed. I suppose conditionals and separate expressions could be an option. As for the specific behaviour I wanted in my code - maybe there are other ways to do it but it was what I came up with in reasonable time. So unless you see some wider problem here I suspect this can be closed. |
I see, thanks for the info. You could try to use overloads for number parsing and For example: <Message Text="$([System.Double]::Parse('1234,56', $([System.Globalization.CultureInfo]::GetCultureInfo('cs-CZ'))))" Importance="High" />
<Message Text="$([System.Double]::Parse('1234,56', $([System.Globalization.CultureInfo]::GetCultureInfo('en-US'))))" Importance="High" /> outputs
so they are parsed differently. I'm closing this issue, but feel free to reopen it if you need additional support. |
Issue Description
Running in Swedish regional settings, certain expressions that involve dividing and rounding values from msbuild properties return different results in msbuild 17 compared to msbuild 16. I suspect it's related to #8710 from 17.8.
Steps to Reproduce
In summary, I take TotalSeconds (double) from a TimeSpan and put that in an msbuild property. Depending on how I then combined dividing and rounding in separate or combined expressions, the output is different.
The following msbuild file show the differences:
Expected Behavior
I don't want to claim this is really the expected output, but it is the actual output on msbuild 16.11:
Actual Behavior
This is the actual output from msbuild 17.8:
Analysis
It seems that on v16, msbuild will honour the decimal comma when it's present in a string msbuild property passed to
Divide
, but not when passed toRound
. ForRound
I assume it is instead perceived as a thousands separator.In v17, it is perceived as a thousands separator also for the
Divide
method.When the different methods are combined into a single expression it seems to work and produce the correct result - I suppose in this case it never round-trips as a string msbuild property. But the expression gets long and difficult to read.
I suspect this is related to the application of InvariantCulture for double TryParse as part of #8710.
I do hesitate to claim this is a bug... Perhaps it is as intended, but it does raise an interesting dilemma:
When a floating point value is put in a string msbuild property, a decimal comma will be used. When later trying to use this property as an argument to something that takes a double, the decimal comma will be silently treated as a thousands separator instead. It is inconsistent. And to make matters worse, I suppose the same syntax will work fine in regions using a decimal point, but then produce incorrect results if run by someone in e.g. Swedish regional format settings.
If double parsing will insist on requiring decimal point, should msbuild not take care to use that also when converting doubles to strings?
So far I haven't found any docs talking about this subject in terms of "best practice" or similar.
Versions & Configurations
No response
The text was updated successfully, but these errors were encountered: