Identical math code working differently on C# and C++

Started by
16 comments, last by vadevaman 9 years, 10 months ago

perhaps you could try to pass it over the boundary as double and cast it back to float on the C side.

Just to make sure, you are saying that you have a function:

void myCFunction(float value);

On the C side.. and if you call it from C# with a value myCFunction(0.2899344f); you receive something different on the C side?

Stefano Casillo
TWITTER: [twitter]KunosStefano[/twitter]
AssettoCorsa - netKar PRO - Kunos Simulazioni

Advertisement

The main problem isn't passing values to and from C#.

The way the two different languages transform calculations into assembly is different. Most notably in both cases some of the intermediate calculations may be done at a higher precision than you've specified. There will also be small differences in the results from library functions like sin(). In addition C# depending on which CPU it's run on may generate different assembly when it's JITted, so the C# result almost certainly won't be identical between different PCs.

If you want reproducibility integer maths is much easier to do that with.

C++ can also be easily disassembled. It's impossible to keep any calculation you do on a computer secret from the owner of that computer. If this is for something like license key validation you should switch to something based on public key cryptography.

C++ can also be easily disassembled.

yes but no... in C# you can get back to the names of the functions and variables. Surely in C++ you will still read the names of the function but the code inside will be much harder to reverse engineering. I understand where the OP is coming from because I went through exactly the same decisions.

I wonder if the OP tested the new .NET native.. that might solve the problem without need to leave C# land.

Stefano Casillo
TWITTER: [twitter]KunosStefano[/twitter]
AssettoCorsa - netKar PRO - Kunos Simulazioni


perhaps you could try to pass it over the boundary as double and cast it back to float on the C side.

Well I tryed it like this:
C#


public void SetVelocity(float lonRoadVelocity,float latRoadVelocity){Sim.Dll_Wheel_SetVelocity(this.nativeWheelObject,lonRoadVelocity,latRoadVelocity);}

C++


    EXPORT_API void Dll_Wheel_SetVelocity(CarWheel* wheel,double lonRoadVelocity,double latRoadVelocity){    wheel->SetVelocity((float)lonRoadVelocity,(float)latRoadVelocity);}

And the result was, that nothing was transfered... the values stayed 0.

And about the question, to be specific I'm not using C, I'm using C++ (the languages should be different)

And currently I'm passing them the way as you described.

Also after some deeper debuging I found out that strangely the difference happens in my wheel class...


void CarWheel::SetVelocity(float lonVel,float latVel)
{
	lonRoadVelocity = lonVel;
	latRoadVelocity = latVel;
}

"lonRoadVelocity = lonVel" is actually "lonRoadVelocity != lonVel"

So its internal??? C++ float mismatched with C++ float? I'm confused....

Edit:

The above "internal" was a false alarm I guess.

Because I removed the "SetVelocity" method and pass the values directly, wheel->lonRoadVelocity = lonRoadVelocity;

and there still is difference, I think I was just confused,

Debug Results:


		latRoadVelocity	-0.15862428	float
		lonRoadVelocity	-0.036250707	float
+		wheel	0x1b75e120 {brake={...} tire={...} suspension={...} ...}	CarWheel *
		wheel->latRoadVelocity	-0.15102120	float
		wheel->lonRoadVelocity	-0.036250707	float

After /arch:SSE2 and /fp:fast the difference actually is notably smaller. In this case for some reason it only occurs in "latRoadVelocity".

"lonRoadVelocity" seems to be 1:1 o nevery frame I debuged, so I'm getting closer

hm weird.. in C# if the signature of the function requires a double, it shouldn't compile if you pass a float to it... did you change the signature of the DLL_Set_velocity on the C# side?

Stefano Casillo
TWITTER: [twitter]KunosStefano[/twitter]
AssettoCorsa - netKar PRO - Kunos Simulazioni

I just noticed there is a inacuracy issue with floats in C++, flaots in C# (atleast in mono) stay the same and are pretty good to work with

but in C++ a float of 0.0091 is actually 0.0091000004 ... that 4 in the end can make a math calc result in wrong calculations.

While "lonRoadVelocity" seems to pass normally now, I dont understnd why the "latRoadVelocity" has a offset, when I pass it the same way...


in C# if the signature of the function requires a double

Sounds right indeed. Maybe it's because I'm using mono?
Anyway when passing a float instead of double, the values stay 0, but when I cast the float to double in C# and pass the double ... well saddly nothing changes.

But like I mentioned, the "lonRoadVelocity" seems to now be 1:1, but for some strange reason the "latRoadVelocity" has an offset.

Edit:

Here are some debug results in a single frame:

In aplication (C#)

debugcsharp.jpg

and results in msvc2010 debug:


w0
lonRoadVelocity    0.027051473    float
latRoadVelocity    0.13362961    float
wheel->lonRoadVelocity    0.027051473    float
wheel->latRoadVelocity    0.14100081    float
w1
lonRoadVelocity    -0.034490682    float
latRoadVelocity    0.13361663    float
wheel->lonRoadVelocity    -0.034490682    float
wheel->latRoadVelocity    0.14098407    float
w2
lonRoadVelocity    0.026764294    float
latRoadVelocity    0.030822765    float
wheel->lonRoadVelocity    0.026764294    float
wheel->latRoadVelocity    0.043717053    float        
w3
lonRoadVelocity    -0.034203805    float
latRoadVelocity    0.030835744    float
wheel->lonRoadVelocity    -0.034203805    float
wheel->latRoadVelocity    0.043733794    float

So the parameters are fine. Now where might that breakpoint be ?

Also: 0.0091000004 is within float precision of 0.0091. It's probably also just a difference with the debug view, not the actual value.


So the parameters are fine.

At w2 lateral speeds:

actual value 0.043717053

"equal" value 0.030822765
0.043717053 - 0.030822765 = 0.012894288
this is 34.59% of difference how come this be fine?

Breakpoint is at my exportFunctions.cpp

Edit: I just noticed something, the latRoadVelocity seem to be used form the last frame... I'll have a deeper look on my main class

Edit2: This is odd, seems like the values are passed quite accurate now, but the calculations are still messed and the wheel's cant find theyr correct slip's...
Is there a possibility that the math function (wich is quite simple) may produce absolutely different results, causing the math to break?

This topic is closed to new replies.

Advertisement