typecasting trouble - converting from int to unsigned long

Trying to convert from fractional minutes to unsigned long milliseconds has revealed some craziness. I am used to casting and implicit casting that goes pretty smoothly in C++. Check out these results. I still can't find a way to cast an expression between int and double into unsigned long.

		double mins, dfactor;
		int    ifactor;
		unsigned long msecs;

		mins = .5;
		dfactor = 60000;
		ifactor = 60000;

		msecs = (unsigned long) (mins * 60000);
		Serial.println(msecs); // 30000  expected!

		msecs = (unsigned long) (mins * dfactor);
		Serial.println(msecs); // 30000

		msecs = (unsigned long) (mins * ifactor);
		Serial.println(msecs); // O

		msecs = (unsigned long) ( mins * (double)ifactor);
		Serial.println(msecs); // 0

		msecs = mins * (unsigned long)ifactor;
		Serial.println(msecs); // 2147480832

		msecs = (unsigned long) ( mins * (unsigned long)ifactor);
		Serial.println(msecs); // 2147480832

int ifactor = 60000 ?
That is not possible.

A double is actually a float in the Arduino.

mins * ifactor ?
A float and integer. Please use typecasting so the compiler knows for sure what to do.
For example: mins * (float) ifactor;
You can do the calculation in float and cast that to unsigned long: (unsigned long) (mins * (float) ifactor)).
As long as ifactor is not above 32767 ofcourse.

You can make things very clear, by using constants with the same type.

float x;          // float
x += 1000.0;
if (x > 500.0) 

int i;          // integer
i += 10;

unsigned long t;  // unsigned long
t *= 5000UL;
if (t < 2000UL)

long l;    // long
l -= 40L;
if (l == 10L)

Write unsigned long constants as unsigned long: 60000UL

Floats always spread by contagion, that's not an issue, the problem with integer
types is that the default is signed 16 bit on the Arduino software - so 60000 is
of type int and is actually -5536. 60000L is long, but that would then need a cast
to unsigned I believe. Multiplying two 16 bit values never promotes to 32 bit in C,
you always have to cast one of the numbers to 32 bit first. As I understand it
this means the compiler cannot actually use a 16x16->32 multiply instruction
and is forced to use 32x32->32 instruction/fragment! (well perhaps the optimiser
spots that).

Moral: always write long constants with an L, and unsigned long constants with UL.
Always write float constants with a decimal point and/or 'e' notation.

I am used to casting and implicit casting that goes pretty smoothly in C++.

That’s good because the Arduino IDE uses C++.

I don't understand why you have double there at all. Perhaps you should try "long"