Asked  7 Months ago    Answers:  5   Viewed   49 times

I am not familiar with PHP at all and had a quick question.

I have 2 variables pricePerUnit and InvoicedUnits. Here's the code that is setting these to values:

$InvoicedUnits = ((string) $InvoiceLineItem->InvoicedUnits);
$pricePerUnit = ((string) $InvoiceLineItem->PricePerUnit);

If I output this, I get the correct values. Lets say 5000 invoiced units and 1.00 for price.

Now, I need to show the total amount spent. When I multiply these two together it doesn't work (as expected, these are strings).

But I have no clue how to parse/cast/convert variables in PHP.

What should I do?

 Answers

68
$rootbeer = (float) $InvoicedUnits;

Should do it for you. Check out Type-Juggling. You should also read String conversion to Numbers.

Wednesday, March 31, 2021
 
turik
answered 7 Months ago
74

David's comment is correct but insufficiently strong. There is no guarantee that doing that calculation twice in the same program will produce the same results.

The C# specification is extremely clear on this point:


Floating-point operations may be performed with higher precision than the result type of the operation. For example, some hardware architectures support an “extended” or “long double” floating-point type with greater range and precision than the double type, and implicitly perform all floating-point operations using this higher precision type. Only at excessive cost in performance can such hardware architectures be made to perform floating-point operations with less precision, and rather than require an implementation to forfeit both performance and precision, C# allows a higher precision type to be used for all floating-point operations. Other than delivering more precise results, this rarely has any measurable effects. However, in expressions of the form x * y / z, where the multiplication produces a result that is outside the double range, but the subsequent division brings the temporary result back into the double range, the fact that the expression is evaluated in a higher range format may cause a finite result to be produced instead of an infinity.


The C# compiler, the jitter and the runtime all have broad lattitude to give you more accurate results than are required by the specification, at any time, at a whim -- they are not required to choose to do so consistently and in fact they do not.

If you don't like that then do not use binary floating point numbers; either use decimals or arbitrary precision rationals.

I don't understand why casting to float in a method that returns float makes the difference it does

Excellent point.

Your sample program demonstrates how small changes can cause large effects. You note that in some version of the runtime, casting to float explicitly gives a different result than not doing so. When you explicitly cast to float, the C# compiler gives a hint to the runtime to say "take this thing out of extra high precision mode if you happen to be using this optimization". As the specification notes, this has a potential performance cost.

That doing so happens to round to the "right answer" is merely a happy accident; the right answer is obtained because in this case losing precision happened to lose it in the correct direction.

How is .net 4 different?

You ask what the difference is between 3.5 and 4.0 runtimes; the difference is clearly that in 4.0, the jitter chooses to go to higher precision in your particular case, and the 3.5 jitter chooses not to. That does not mean that this situation was impossible in 3.5; it has been possible in every version of the runtime and every version of the C# compiler. You've just happened to run across a case where, on your machine, they differ in their details. But the jitter has always been allowed to make this optimization, and always has done so at its whim.

The C# compiler is also completely within its rights to choose to make similar optimizations when computing constant floats at compile time. Two seemingly-identical calculations in constants may have different results depending upon details of the compiler's runtime state.

More generally, your expectation that floating point numbers should have the algebraic properties of real numbers is completely out of line with reality; they do not have those algebraic properties. Floating point operations are not even associative; they certainly do not obey the laws of multiplicative inverses as you seem to expect them to. Floating point numbers are only an approximation of real arithmetic; an approximation that is close enough for, say, simulating a physical system, or computing summary statistics, or some such thing.

Monday, June 7, 2021
 
Palladium
answered 5 Months ago
65

Your code isn't very helpful. But if I understand you right do it like this

string str;
if (!getline(cin, str))
{
  // error: didn't get any input
}
istringstream ss(str);
float f;
if (!(ss >> f))
{
  // error: didn't convert to a float
}

There's no need to use fail.

Monday, August 16, 2021
 
Mahdi
answered 2 Months ago
56

Use number_format to replace the , with .

Like this:

number_format($value, 8, '.') // 8 = number of decimals, . = decimal separator

However, your problem seems to be related to the current locale. You need to look into the following: setlocale() and localeconv

setlocale(LC_ALL, 'en_US'); // NOT TESTED, read up on the appropriate syntax

This is the appropriate way of doing this, the alternative would be (as suggested below), to do a str_replace(',', '.'), but you have to do the reverse every time you want to output strings.

There is another option though, you can set the MySQL locale to en_US.

Tuesday, August 24, 2021
 
Farnabaz
answered 2 Months ago
87

No no no no no no no no no.

Use an NSNumberFormatter. This is why it exists. -floatValue and -doubleValue are merely quick-and-easy temporary fixes, but they fail in bad ways. For example:

NSLog(@"%f", [@"123" floatValue]); //logs 123.0000
NSLog(@"%f", [@"abc" floatValue]); //logs 0.0000
NSLog(@"%f", [@"0" floatValue]);   //logs 0.0000
NSLog(@"%f", [@"42" floatValue]);  //logs 42.0000
NSLog(@"%f", [@"42x" floatValue]); //logs 42.0000

-floatValue is unable to distinguish between a proper number (@"0") and an invalid one (@"abc").

NSNumberFormatter, on the other hand, will give you nil if it can't parse it, and an NSNumber if it can. It also takes things like currency symbols, region-specific decimal and thousands separators, and the user's locale into account. -floatValue and friends do not.

See this related question for more info: How to convert an NSString into an NSNumber

Friday, October 15, 2021
 
Krzysztof Kaczor
answered 1 Week ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :