Stop Rounding with NSExpression in Calculator [duplicate] - xcode

I want to calculate a string, which I'm doing by this:
NSExpression *expression = [NSExpression expressionWithFormat:calculationString];
float result = [[expression expressionValueWithObject:nil context:nil] floatValue];
NSLog(#"%f", result);
The problem is, when calculationstring is 1/2, the result is 0. I tried to change float with double and NSNumber and the %f to %f and %#, but I always just get 0. What to I have to change?
Also if it matters, I am in Europe, so I have commas instead of points for this value, but it shouldn't matter as I am logging with %f which shows it as points. Just for information

Basically, you just need to tell it that you are performing floating point operation,
1.0/2
1.0/2.0
1/2.0
Will all work

Typing in NSExpression is much like in C: literals that look like integers (no decimal point/comma) are treated as integers and thus use integer division. (Under integer division, 1/2 is zero. If you want 0.5, you need floating point division.) This happens when the expression is parsed and evaluated, so attempting to change the type of the result or the formatting of the output has no effect -- those things happen after parsing and evaluation.
If your calculationString is entirely under your control, it's easy to make sure that you use floating point literals anywhere you want floating point division. (That is, use 1.0/2 instead of 1/2.) If not, you'll need to change it such that it does -- here it's probably better to decompose the parsed NSExpression and change an operand rather than munge the string.
Followup edit on the "decompose" bit: String munging in content that you know to have higher-order structure is generally problematic. And with NSExpression, you already have a parser (who's smarter than a simple regex) decomposing the string for you — that is in fact what NSExpression is all about.
So, if you're working with a user-provided string, don't try to change the expression by changing the string. Let NSExpression parse it, then use properties of the resulting object to pick it apart into its constituent expressions. If your string is simply "1/2", then your expression has an array of two arguments and the function "divide:by:" — you can replace it with an equivalent function where one of the arguments is explicitly a floating-point value:
extension NSExpression {
var floatifiedForDivisionIfNeeded: NSExpression {
if function == "divide:by:", let args = arguments, let last = args.last,
let firstValue = args.first?.constantValue as? NSNumber {
let newFirst = NSExpression(forConstantValue: firstValue.doubleValue)
return NSExpression(forFunction: function, arguments: [newFirst, last])
} else {
return self
}
}
}

I think You need to User DDMathParser Which is best in this situation. I have used it in One of my project which is facing same problem as you have faced
DDMathEvaluator *eval = [DDMathEvaluator defaultMathEvaluator];
id value=[eval evaluateString:#"1/2" withSubstitutions:nil error:&error];
NSLog(#"Result %#",value);
Result 0.5

Rickster's solution worked, but had problems with expressions like 5*5/2, where the first argument (here 5*5) was not just a number.
I found a different solution here that works for me: https://stackoverflow.com/a/46554342/6385925

for people who still have this problem i did a somewhat quick fix:
extension String {
var mathExpression: String {
var returnValue = ""
for value in newString.components(separatedBy: " ") {
if value.isOperator {
returnValue += value
} else {
returnValue += "\(Double(value) ?? 0)"
}
}
return returnValue
}
var isOperator: Bool {
["+", "-", "/", "x", "*"].contains(self)
}
}

Related

Integers converted to strings do not work as expected

Issue comparing str() to what I'd expect is their String form
Code :
int i = 2;
String r = str(i);
println(r);
if (r == "2") {
println("String works");
} else println("String doesnt work");
if (i == 2) {
println("Integer works");
} else println("Integer doesnt work");
Prints :
2
String doesnt work
Integer works
The second if statement is a copy paste of the first, with only the variable and value changed so theres nothing wrong with my if statement
Processing documentation states (about str()):
Converts a value of a primitive data type (boolean, byte, char, int, or float) to its String
representation. For example, converting an integer with str(3) will return the String value of "3",
converting a float with str(-12.6) will return "-12.6", and converting a boolean with str(true) will
return "true".
Also doesnt work with str(2) == "2" or str(i) == "2"
How do I fix this and get it to work (without converting it back to an integer because that would make my code a bit ugly)
You should not compare String values using ==. Use the equals() function instead:
if (r.equals("2")) {
From the reference:
To compare the contents of two Strings, use the equals() method, as in if (a.equals(b)), instead of if (a == b). A String is an Object, so comparing them with the == operator only compares whether both Strings are stored in the same memory location. Using the equals() method will ensure that the actual contents are compared. (The troubleshooting reference has a longer explanation.)
More info here: How do I compare strings in Java?

Inherent math operation in Java

I'm writing essentially a small calaculator where you input two numbers, an operand like "+, -, *, /" etc and it'll preform that function.
My initial thoughts have been to just have the variables get entered by the user, than just have them computed as imputed. I would like to do it this way, as to avoid writing several if else statements and keeping things a bit cleaner. But I can't find a place explaining how to inherently compute the values and imputed characters.
package hw2p1;
import java.util.Scanner;
import javax.script.*;
public class Calculator {
public static void PrintCalculator(){
Scanner input = new Scanner(System.in);
double num1; //1st entered number
double num2; //2nd entered number
String val1; //Math operator like + - * /.
double math1; //the results.
String equation = "";
System.out.print("Enter the first number:");
num1 = input.nextDouble();
System.out.print("Enter the second number:");
num2 = input.nextDouble();
System.out.print("Enter an operator:");
val1 = input.next();
I know this is incomplete, but I don't know/can't find the logic on how to string the three inputted values together and compute them.
The simplest solution would be
public static double calculate(double a, String op, double b) {
switch(op) {
case "+": return a+b;
case "-": return a-b;
case "*": return a*b;
case "/": return a/b;
case "%": return a%b;
case "^": return Math.pow(a, b);
default: throw new IllegalArgumentException("no such operator '"+op+"'");
}
}
which is semantically equivalent to a sequence of if-else statements, but clearly showing the intention and potentially more efficient, though there’s not much worth in speculating about performance here.
It can be invoked like
double math1 = calculate(num1, val1, num2); //the results.
but you really should retink your variable naming scheme. If you have to append a comment telling the purpose behind every declaration, you’re clearly doing something wrong. Why not naming the variables, e.g. firstInputNumber, secondInputNumber, operator and result in the first place? Then, you don’t need the comments telling the variable’s purposes.
I could not remove if-else but may be you can try something like this
public static void main(String[] args) {
int result = operate("+").applyAsInt(10, 20);
System.out.println(result);
}
private static IntBinaryOperator operate(String op){
switch(op){
case "+": return Math::addExact;
case "-": return Math::subtractExact;
//other cases
}
throw new RuntimeException("incorrect operator");
}
One issue though, Math do not have methods for double
tl;dr
You have to explicitly state that "+" means addition.
Long Anwser
When the user types something when your program runs, all of it is just characters. It's up to your program to interpret those characters to do something meaningful. Scanner can be helpful with this because it knows how to interpret the characters 1234 as an int. However, beyond data for the built-in types, Scanner is completely dumb.
In building your own calculator program, you are basically writing a simplified version of the Java compiler. The compiler is a program which reads characters from a file and converts them into something that can execute on a Java Virtual Machine. You will do much of the same thing in your own calculator program. This means that you have to explicitly write the rules that interpret characters that represent mathematical operators into the operations that they actually perform.
If you are interested in learning more about this topic, you can do some research on compilers and interpreters. They are generally made of two pieces: the lexical analyzer, or lexer, and the parser. This is all especially necessary if you want to allow the user to type in a complete mathematical expression like 2 + 3 rather than prompting them for each piece of the expression individually.
I hope this gives you some terminology that you can use in a Google search.

In Swift, how do you convert a String to Int64?

I am loading in lines from a text file with very large numbers. String has the toInt method, but how do you convert a string to an Int64 which will be able to handle the large numbers?
I don't see a toInt64 method or a toLong etc. There must be a way, but I haven't found anything by searching yet.
Alternatively I guess I could read the numbers in the string digit by digit (or by groups of digits) and then add them together with appropriate factors of ten, but that seems like overkill. Or maybe the proper way is to read the data in a binary form and convert it that way?
Thanks
As of Swift 2.1.1 you can simply initialize Int64 with String
let number: Int64? = Int64("42")
If you don't mind using NSString, you can do this:
let str = "\(LLONG_MAX)"
let strAsNSString = str as NSString
let value = strAsNSString.longLongValue
Note that unlike toInt(), longLongValue will return 0 if the string is not a legal number whereas toInt() will return nil in that case.
import Darwin
let strBase10 = "9223372036854775807"
let i64FromBase10 = strtoll(strBase10, nil, 10)
let strBase16 = "0xFFFFFFFFFFFFFFFF"
let i64FromBase16 = strtoll(strBase16, nil, 16)
strtoll means STRingTOLongLong
http://www.freebsd.org/cgi/man.cgi?query=strtoll
import Darwin
let str = ...
let i = strtoll(str, nil, 10)

How to return-7-6-5-4-3-2-1012345678910111213

Code below is in Objective C in Xcode. I am trying to return -7-6-5-4-3-2-1012345678910111213 as the method is expecting that response. number = -7 and otherNumber = 13 How do I return the series of numbers? I tried the method below but with no success...
while (number < otherNumber) {
++number;
return number;
}
Another thing to look out for is how your parameters are getting passed in to the method. Since we dont know if "number" is always going to be less than "otherNumber" you should check to find out which of the two numbers being passed in is lower before using them in your while loop.
this is very similar to the previous post but it might make it a tad clearer:
//find which number is low and which is high and set it accordingly
while (low <= high){
//then append low to end of string
++low;
}
//return your string
And this handles the case when the numbers are equal
In Objective-C, methods can only have one return value.
If your method returns an array, something like this would work:
// Create an NSMutableArray
while (number < otherNumber) {
// Add the number to the array
++number;
}
// Return the array
Or, similarly, if your method returns a string:
// Create an NSMutableString
while (number < otherNumber) {
// Append the number to the end of the string
++number;
}
// Return the string
A few notes:
your conditional, number < otherNumber, won't capture the case where number == otherNumber. Since in your example otherNumber is 13, and you want that included, you may want to use number <= otherNumber.
you can only compare scalar numbers (like NSInteger or CGFloat) with the inequality operators (like < and >). However, you can only add objects to NSMutableArray and NSMutableString. So you'll need to convert between the scalar numbers and NSNumber as appropriate.
Since it looks like you're learning Objective-C, note that this is different from Swift, which does allow methods to return multiple values.

Best way to write a conversion function

Let's say that I'm writing a function to convert between temperature scales. I want to support at least Celsius, Fahrenheit, and Kelvin. Is it better to pass the source scale and target scale as separate parameters of the function, or some sort of combined parameter?
Example 1 - separate parameters:
function convertTemperature("celsius", "fahrenheit", 22)
Example 2 - combined parameter:
function convertTemperature("c-f", 22)
The code inside the function is probably where it counts. With two parameters, the logic to determine what formula we're going to use is slightly more complicated, but a single parameter doesn't feel right somehow.
Thoughts?
Go with the first option, but rather than allow literal strings (which are error prone), take constant values or an enumeration if your language supports it, like this:
convertTemperature (TempScale.CELSIUS, TempScale.FAHRENHEIT, 22)
Depends on the language.
Generally, I'd use separate arguments with enums.
If it's an object oriented language, then I'd recommend a temperature class, with the temperature stored internally however you like and then functions to output it in whatever units are needed:
temp.celsius(); // returns the temperature of object temp in celsius
When writing such designs, I like to think to myself, "If I needed to add an extra unit, what would design would make it the easiest to do so?" Doing this, I come to the conclusion that enums would be easiest for the following reasons:
1) Adding new values is easy.
2) I avoid doing string comparison
However, how do you write the conversion method? 3p2 is 6. So that means there are 6 different combinations of celsius, Fahrenheit, and kelvin. What if I wanted to add a new temperate format "foo"? That would mean 4p2 which is 12! Two more? 5p2 = 20 combination. Three more? 6p2 = 30 combinations!
You can quickly see how each additional modification requires more and more changes to the code. For this reason I don't do direct conversions! Instead, I do an intermediate conversion. I'd pick one temperature, say Kelvin. And initially, I'd convert to kelvin. I'd then convert kelvin to the desired temperature. Yes, It does result in an extra calculation. However, it makes scalling the code a ton easier. adding adding a new temperature unit will always result in only two new modifications to the code. Easy.
A few things:
I'd use an enumerated type that a syntax checker or compiler can check rather than a string that can be mistyped. In Pseudo-PHP:
define ('kCelsius', 0); define ('kFarenheit', 1); define ('kKelvin', 2);
$a = ConvertTemperature(22, kCelsius, kFarenheit);
Also, it seems more natural to me to place the thing you operate on, in this case the temperature to be converted, first. It gives a logical ordering to your parameters (convert -- what? from? to?) and thus helps with mnemonics.
Your function will be much more robust if you use the first approach. If you need to add another scale, that's one more parameter value to handle. In the second approach, adding another scale means adding as many values as you already had scales on the list, times 2. (For example, to add K to C and F, you'd have to add K-C, K-F, C-K, and C-F.)
A decent way to structure your program would be to first convert whatever comes in to an arbitrarily chosen intermediate scale, and then convert from that intermediate scale to the outgoing scale.
A better way would be to have a little library of slopes and intercepts for the various scales, and just look up the numbers for the incoming and outgoing scales and do the calculation in one generic step.
In C# (and probaly Java) it would be best to create a Temperature class that stores temperatures privately as Celcius (or whatever) and which has Celcius, Fahrenheit, and Kelvin properties that do all the conversions for you in their get and set statements?
Depends how many conversions you are going to have. I'd probably choose one parameter, given as an enum: Consider this expanded version of conversion.
enum Conversion
{
CelsiusToFahrenheit,
FahrenheitToCelsius,
KilosToPounds
}
Convert(Conversion conversion, X from);
You now have sane type safety at point of call - one cannot give correctly typed parameters that give an incorrect runtime result. Consider the alternative.
enum Units
{
Pounds,
Kilos,
Celcius,
Farenheight
}
Convert(Unit from, Unit to, X fromAmount);
I can type safely call
Convert(Pounds, Celcius, 5, 10);
But the result is meaningless, and you'll have to fail at runtime. Yes, I know you're only dealing with temperature at the moment, but the general concept still holds (I believe).
I would choose
Example 1 - separate parameters: function convertTemperature("celsius", "fahrenheit", 22)
Otherwise within your function definition you would have to parse "c-f" into "celsius" and "fahrenheit" anyway to get the required conversion scales, which could get messy.
If you're providing something like Google's search box to users, having handy shortcuts like "c-f" is nice for them. Underneath, though, I would convert "c-f" into "celsius" and "fahrenheit" in an outer function before calling convertTemperature() as above.
In this case single parameters looks totally obscure;
Function convert temperature from one scale to another scale.
IMO it's more natural to pass source and target scales as separate parameters. I definitely don't want to try to grasp format of first argument.
I would make an enumeration out of the temperature types and pass in the 2 scale parameters. Something like (in c#):
public void ConvertTemperature(TemperatureTypeEnum SourceTemp,
TemperatureTypeEnum TargetTemp,
decimal Temperature)
{}
I'm always on the lookout for ways to use objects to solve my programming problems. I hope this means that I'm more OO than when I was only using functions to solve problems, but that remains to be seen.
In C#:
interface ITemperature
{
CelciusTemperature ToCelcius();
FarenheitTemperature ToFarenheit();
}
struct FarenheitTemperature : ITemperature
{
public readonly int Value;
public FarenheitTemperature(int value)
{
this.Value = value;
}
public FarenheitTemperature ToFarenheit() { return this; }
public CelciusTemperature ToCelcius()
{
return new CelciusTemperature((this.Value - 32) * 5 / 9);
}
}
struct CelciusTemperature
{
public readonly int Value;
public CelciusTemperature(int value)
{
this.Value = value;
}
public CelciusTemperature ToCelcius() { return this; }
public FarenheitTemperature ToFarenheit()
{
return new FarenheitTemperature(this.Value * 9 / 5 + 32);
}
}
and some tests:
// Freezing
Debug.Assert(new FarenheitTemperature(32).ToCelcius().Equals(new CelciusTemperature(0)));
Debug.Assert(new CelciusTemperature(0).ToFarenheit().Equals(new FarenheitTemperature(32)));
// crossover
Debug.Assert(new FarenheitTemperature(-40).ToCelcius().Equals(new CelciusTemperature(-40)));
Debug.Assert(new CelciusTemperature(-40).ToFarenheit().Equals(new FarenheitTemperature(-40)));
and an example of a bug that this approach avoids:
CelciusTemperature theOutbackInAMidnightOilSong = new CelciusTemperature(45);
FarenheitTemperature x = theOutbackInAMidnightOilSong; // ERROR: Cannot implicitly convert type 'CelciusTemperature' to 'FarenheitTemperature'
Adding Kelvin conversions is left as an exercise.
By the way, it doesn't have to be more work to implement the three-parameter version, as suggested in the question statement.
These are all linear functions, so you can implement something like
float LinearConvert(float in, float scale, float add, bool invert);
where the last bool indicates if you want to do the forward transform or reverse it.
Within your conversion technique, you can have a scale/add pair for X -> Kelvin. When you get a request to convert format X to Y, you can first run X -> Kelvin, then Kelvin -> Y by reversing the Y -> Kelvin process (by flipping the last bool to LinearConvert).
This technique gives you something like 4 lines of real code in your convert function, and one piece of data for every type you need to convert between.
Similar to what #Rob #wcm and #David explained...
public class Temperature
{
private double celcius;
public static Temperature FromFarenheit(double farenheit)
{
return new Temperature { Farhenheit = farenheit };
}
public static Temperature FromCelcius(double celcius)
{
return new Temperature { Celcius = celcius };
}
public static Temperature FromKelvin(double kelvin)
{
return new Temperature { Kelvin = kelvin };
}
private double kelvinToCelcius(double kelvin)
{
return 1; // insert formula here
}
private double celciusToKelvin(double celcius)
{
return 1; // insert formula here
}
private double farhenheitToCelcius(double farhenheit)
{
return 1; // insert formula here
}
private double celciusToFarenheit(double kelvin)
{
return 1; // insert formula here
}
public double Kelvin
{
get { return celciusToKelvin(celcius); }
set { celcius = kelvinToCelcius(value); }
}
public double Celcius
{
get { return celcius; }
set { celcius = value; }
}
public double Farhenheit
{
get { return celciusToFarenheit(celcius); }
set { celcius = farhenheitToCelcius(value); }
}
}
I think I'd go whole hog one direction or another. You could write a mini-language that does any sort of conversion like units does:
$ units 'tempF(-40)' tempC
-40
Or use individual functions like the recent Convert::Temperature Perl module does:
use Convert::Temperature;
my $c = new Convert::Temperature();
my $res = $c->from_fahr_to_cel('59');
But that brings up an important point---does the language you are using already have conversion functions? If so, what coding convention do they use? So if the language is C, it would be best to follow the example of the atoi and strtod library functions (untested):
double fahrtocel(double tempF){
return ((tempF-32)*(5/9));
}
double celtofahr(double tempC){
return ((9/5)*tempC + 32);
}
In writing this post, I ran across a very interesting post on using emacs to convert dates. The take-away for this topic is that it uses the one function-per-conversion style. Also, conversions can be very obscure. I tend to do date calculations using SQL because it seems unlikely there are many bugs in that code. In the future, I'm going to look into using emacs.
Here is my take on this (using PHP):
function Temperature($value, $input, $output)
{
$value = floatval($value);
if (isset($input, $output) === true)
{
switch ($input)
{
case 'K': $value = $value - 273.15; break; // Kelvin
case 'F': $value = ($value - 32) * (5 / 9); break; // Fahrenheit
case 'R': $value = ($value - 491.67) * (5 / 9); break; // Rankine
}
switch ($output)
{
case 'K': $value = $value + 273.15; break; // Kelvin
case 'F': $value = $value * (9 / 5) + 32; break; // Fahrenheit
case 'R': $value = ($value + 273.15) * (9 / 5); break; // Rankine
}
}
return $value;
}
Basically the $input value is converted to the standard Celsius scale and then converted back again to the $output scale - one function to rule them all. =)
My vote is two parameters for conversion types, one for the value (as in your first example). I would use enums instead of string literals, however.
Use enums, if your language allows it, for the unit specifications.
I'd say the code inside would be easier with two. I'd have a table with pre-add, multiplty, and post-add, and run the value through the item for one unit, and then through the item for the other unit in reverse. Basically converting the input temperature to a common base value inside, and then out to the other unit. This entire function would be table-driven.
I wish there was some way to accept multiple answers. Based on everyone's recommendations, I think I will stick with the multiple parameters, changing the strings to enums/constants, and moving the value to be converted to the first position in the parameter list. Inside the function, I'll use Kelvin as a common middle ground.
Previously I had written individual functions for each conversion and the overall convertTemperature() function was merely a wrapper with nested switch statements. I'm writing in both classic ASP and PHP, but I wanted to leave the question open to any language.

Resources