Float math using only variables, how to define decimal places?

unsigned long z = pulseIn(2, HIGH);
unsigned long y = pulseIn(2, LOW);
unsigned long x = z + y;

float w = (float) z / (float) x;  // although why?
int v = w * 4000;

// why not
int v = (int) ( 4000UL * z / x ); // it does the math in 32 bit unsigned THEN casts the result to signed 16 bit.

I am expecting an integer output for v: Percentage w% * 4000 = 0 to 4000. What am I missing here?

One answer is variable types and casting.

Also AVR has no FPU and only has 32 bit floats whereas Arduino supports 64 bit integers good to 19 places and can do those faster than floats good to 6 places, here's the missing:

the decimal point is just part of the representation. If I want to keep meters to 3 places accuracy then I make my unit micrometers (3 places beyond accuracy to divide into without rounding loss) and work in 32 or 64 bits. The value stored is meters x 1,000,000 but I stick a decimal point in at millions and only show the next 3 digits when printing to 3 places.
Integer divide ( / ) and remainder ( % ) operations let you split integers on a decimal place. You print the higher order value first then a decimal place then pad in zeros as needed (for 3 places: if < 100; if < 10 ) before printing any remainder.
You could use sprintf() but that includes a lot of code and a buffer. And format string specifiers.