• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

Programming |OT| C is better than C++! No, C++ is better than C

oxrock

Gravity is a myth, the Earth SUCKS!
I've decided that I need to add c++ to my very limited skill set and have been doing what I can to teach myself. I'm slightly passed the "hello world" stage but probably not by all the much. I decided a fun way to teach myself was to remake an old python script I did a while back in C++. I've been running into trouble trying to figure out classes in c++ and I'm hoping I might get some assistance.

header file:
Code:
#pragma once
#include <vector>
#include <string>
#include <iostream>


using namespace std;

class boxer 
{
private:
	bool gender;
	int mHP, tournaments;
	string fName, lName;
	vector<int> stats;
public:	
	boxer(bool sex, vector<string> boys, vector<string> girls, vector<string> family);
	vector<int>getStats();
	void setStats(vector<int> stats);
	~boxer();
};

boxer.cpp:
Code:
#include "stdafx.h"
#include "boxer.h"
#include <vector>
#include <string>


boxer::boxer(bool sex, vector<string> boys, vector<string> girls, vector<string> family) {
	bool gender = sex;
	int mHP = 100;
	int tournaments = 0;
	vector<int> stats = { 6,5,4,3,2,1 };

	if (gender) {
		string fName = boys[rand() % (boys.size() - 1)];
	}
	else {
		string fName = girls[rand() % (girls.size() - 1)];
	}
};


boxer::vector<int> getStats() {
	return vector<int> {1, 2, 3, 4, 5,6};
};

boxer::setStats(vector<int> stats) {

}

boxer::~boxer()
{
	delete &gender;
	delete &mHP;
	delete &fName;
	delete &lName;
};

main program:

Code:
#include "stdafx.h"
#include "math.h"
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>     
#include <time.h> 
#include <boxer.h>


using namespace std;



int main()
{
	srand(time(NULL));
	vector<string> femaleNames = { "Tonya","Jane","Jessica","Amy","Susan","Tammy","Erica", "Joselyn","Veronica","Laura","Betsy" };
	vector<string> maleNames = { "James","Jason","Michael","Christoper","Eric","Cameron","Ralph","Tony","John","Timothy","Craig" };
	vector<string> familyNames = { "Jones","Smith","Malloy","Potter","Miller","Doe","Simmons","Johnson","Conner","Monk","Simpson","Mars" };
	
	boxer::boxer(true, malesNames, femaleNames, familyNames)  test;
	
	cin.get();

    return 0;
}


I'm using visual studio 2015 if that's relevant. Anyway, I'm getting IDE errors trying to connect header function templates to functions in my boxer.cpp file, also just simply creating the object from main file isn't happening. It would be great if someone more experienced could take a look and explain how I went so wrong and maybe show me the correct way. Thanks guys.
 

MrCuddle

Member
Code:
boxer::boxer(bool sex, vector<string> boys, vector<string> girls, vector<string> family) {
	bool gender = sex;
	int mHP = 100;
	int tournaments = 0;
	vector<int> stats = { 6,5,4,3,2,1 };

	if (gender) {
		string fName = boys[rand() % (boys.size() - 1)];
	}
	else {
		string fName = girls[rand() % (girls.size() - 1)];
	}
};

You're declaring new local variables, not assigning your member variables.

Code:
boxer::vector<int> getStats() {
	return vector<int> {1, 2, 3, 4, 5,6};
};
The return type should be specified first. vector<int> boxer::getStats()

Code:
boxer::~boxer()
{
	delete &gender;
	delete &mHP;
	delete &fName;
	delete &lName;
};
Do NOT delete variables allocated on the stack. You should only use the delete keyword if you've allocated memory with the new keyword. And you should only allocate memory with the new keyword if you have a good reason for doing so.

Code:
boxer::boxer(true, malesNames, femaleNames, familyNames)  test;

Should be boxer test(true, malesNames, femaleNames, familyNames);
boxer is a class, not a namespace.
 

oxrock

Gravity is a myth, the Earth SUCKS!
Code:
boxer::boxer(bool sex, vector<string> boys, vector<string> girls, vector<string> family) {
	bool gender = sex;
	int mHP = 100;
	int tournaments = 0;
	vector<int> stats = { 6,5,4,3,2,1 };

	if (gender) {
		string fName = boys[rand() % (boys.size() - 1)];
	}
	else {
		string fName = girls[rand() % (girls.size() - 1)];
	}
};

You're declaring new local variables, not assigning your member variables.

Code:
boxer::vector<int> getStats() {
	return vector<int> {1, 2, 3, 4, 5,6};
};
The return type should be specified first. vector<int> boxer::getStats()

Code:
boxer::~boxer()
{
	delete &gender;
	delete &mHP;
	delete &fName;
	delete &lName;
};
Do NOT delete variables allocated on the stack. You should only use the delete keyword if you've allocated memory with the new keyword. And you should only allocate memory with the new keyword if you have a good reason for doing so.

Code:
boxer::boxer(true, malesNames, femaleNames, familyNames)  test;

Should be boxer test(true, malesNames, femaleNames, familyNames);
boxer is a class, not a namespace.
First of all, thanks for responding. I appreciate the help. Now to continue my questioning! in the line "boxer test(true, malesNames, femaleNames, familyNames)" which I replaced via your suggestion, the class name "boxer" is underlined red with the error text "Error: Identifier 'boxer' is undefined". I think it may have to do with the fact that my line up top "#include <boxer.h>" is underlined red with a msg saying "Error: cannot open source file boxer.h". What could be causing this problem? I've checked like a million times, my header file name is boxer.h and there's no typo in the "include" call, so I have no idea where else I may of gone wrong.
 

V_Arnold

Member
I can answer that if I remember c syntax correctly:
Because it is not a standard library, but a file you provided, you can omit the <> part, and just use #include "boxer.h"? Or do I remember this wrong? :p
 

oxrock

Gravity is a myth, the Earth SUCKS!
I can answer that if I remember c syntax correctly:
Because it is not a standard library, but a file you provided, you can omit the <> part, and just use #include "boxer.h"? Or do I remember this wrong? :p

That was it, things are working as expected currently. Thanks a bunch for the help guys.
 

MrCuddle

Member
I think it may have to do with the fact that my line up top "#include <boxer.h>" is underlined red with a msg saying "Error: cannot open source file boxer.h". What could be causing this problem? I've checked like a million times, my header file name is boxer.h and there's no typo in the "include" call, so I have no idea where else I may of gone wrong.

Use
#include "boxer.h"

I'll leave the nitty gritty details to someone with a bit more experience(calling Dr.Cpp_is_king). But quotation marks will search in the same path as the file you're currently in, which is great for including user made files, while angle brackets will search in an implementation defined location, which is great for including stuff from the standard library.
 

oxrock

Gravity is a myth, the Earth SUCKS!
Now i just have to learn how to properly deconstruct objects, I'll try on my own a while before bothering you all again though. Thanks again guys.
 
Unrelated comment but don't ever use
Code:
using namespace
in a header. That propagates down the include chain so that every file that includes that header file (directly or indirectly) gets it too. You might get namespace issues somewhere later down the line and at the very least you've defeated the purpose of namespaces.
 

JeTmAn81

Member
About this, I've wanted to avoid using Java to develop some software for Android...

Would you, by any chance, know how hard it is to use C# / F# and Unity for this? I may try this summer...

(Although one of the projects need SQL and Unicode support, and not a lot of fancy graphics, and I'm not sure Unity is a better solution for this than normal Android framework, even if I really don't like working with Java)

Well, Microsoft just bought Xamarin so I think eventually you'll be able to use Visual Studio to easily write Android projects in C#. For now it might be easiest to just write some Java, it's not that bad especially if you already write C#.
 
Unrelated comment but don't ever use
Code:
using namespace
in a header. That propagates down the include chain so that every file that includes that header file (directly or indirectly) gets it too. You might get namespace issues somewhere later down the line and at the very least you've defeated the purpose of namespaces.
Yeah, in general any "using x" in a c++ header ends up being trouble. Unless it's scoped, obviously.
 

Makai

Member
Absolute basics of F# - https://dungpa.github.io/fsharp-cheatsheet/

I assume you are using Visual Studio, but this works in MonoDevelop or Xamarin with the right build settings

Install Visual Studio Tools for Unity
Make an F# class library
Configuration Manager -> Release
Project -> Properties -> Configuration -> Release
Project -> Properties -> Application -> Target Framework -> Unity 3.5 .net (whichever version you need for your platform)
Project -> Properties -> Build -> Output Path - set this to a folder in the Unity assets folder. I use "Plugins".
Build DLL
MonoBehaviours inside the DLL can now be attached to GameObjects

Scripts must have an empty constructor, inherit from MonoBehaviour, and not be defined in a module.

Code:
namespace Namespace
open UnityEngine

type Script () =
    inherit MonoBehavhiour ()

    let log = Debug.Log

    member this.Start () =
        log "Start"

    member this.Update () =
        log "Update"

    member this.OnDestroy () =
        log "Goodbye, world"

Expose script variables so they can be modified by the editor

Code:
let [<SerializeField>] mutable variable = "default value"

Force a component to be added to GameObject

Code:
[<RequireComponent(typeof<MeshFilter>)>]
type Script () =
    inherit MonoBehaviour ()

GOTCHAS

F#'s ignore function causes Unity to fatally crash

No forward declarations in F#. Functions can only call other functions which are above them in the file. Files can only call other files which are above them in the solution. This prevents spaghetti code.

Functions without arguments are bindings and will only execute once at app start. Use () as an argument to execute every time

Code:
let mutable always68 = 67
let mutateOnce = always68 <- always68 + 1

let mutable variable = 67
let mutate () = variable <- variable + 1

Some API methods can only be executed in the main thread. This includes creating GameObjects and loading resources. Only call these in a MonoBehaviour method such as Start or Update. Bindings are executed outside main thread and will crash app if they call one of these methods. Use lazy keyword to delay execution of bindings until is called by a MonoBehaviour method. Use .Value to get value in lazy binding

Code:
let load<'T when 'T :> Object> filepath = Resources.Load<'T> filepath

let crashesApp = load<Sprite> "Sprites/Mario"

let sprite = lazy load<Sprite> "Sprites/Mario"

let spriteName () = sprite.Value.name
 

Makai

Member
Game loop class has the only variable in the project - the entire game state. This variable is a record, and it includes a list of all entities in the game and current player input. There's a function which takes a given game state and returns the next one, and the variable is updated with this every frame. Update the view based on the current game state every frame.

Code:
type Loop () =
    inherit MonoBehaviour ()

    let mutable state = [player]

    let view = EntityViewPool ()

    let nextState _ = failwith "Not implemented"

    member this.Update () =
        view.Update state
        state <- nextState state

Entities implement an interface so the game state and view can be updated uniformly.

Code:
type IState =
    abstract Next : Gamepad -> IState
    abstract Location : Location
    abstract Sprite : Sprite

Creating and destroying GameObjects every frame is expensive, so make a pool of GameObjects that persist for the life of the app. A set number is hidden on the sidelines and they are activated when they're needed. Make sure the number of GameObjects exceeds the maximum number of entities you will have on any frame.

Code:
[<AbstractClass>]
type StateView<'TState> () =   
    inherit MonoBehaviour ()

    abstract member SetState : 'TState -> unit
   
    member this.Show visible =
        this.gameObject.SetActive visible

type ViewPool<'TState, 'TView when 'TView :> StateView<'TState>> (childName, parentName, totalKeys) =
    
    let parent = lazy (GameObject parentName).transform

    let keys = [0..totalKeys - 1]

    let createView i =
        let name = childName + i.ToString ()
        let obj = GameObject name
        obj.transform.parent <- parent.Value
        let view = obj.AddComponent<'TView> ()
        i, view

    let views =
        lazy
        List.map createView keys
        |> Map.ofList 

    let disableView _ (view : 'TView) =
        view.Show false

    let disableViews () =
        Map.iter disableView views.Value

    let updateView (states : 'TState list) key =
         let view = views.Value.[key]
         view.Show true
         view.SetState states.[key]
    
    member this.SetStates states =
        disableViews ()
        List.iter (updateView states) [0..states.Length - 1]

You might want to make a few pools for different jobs. If you're making a fighting game, you might want a pool for fighter/projectile sprites and a pool for displaying hitboxes.

Code:
[<RequireComponent(typeof<SpriteRenderer>)>]
type SpriteView () = 
    inherit MonoBehaviour ()

    member this.Renderer =
        this.gameObject.GetComponent<SpriteRenderer>()

    member this.SetSprite sprite =
        this.Renderer.sprite <- sprite

[<RequireComponent(typeof<SpriteView>)>]
type EntityView () =
    inherit StateView<IState> ()
    
    let locationToVector3 (x, y) =
        Vector3 (single x, single y, 0.0f)
 
    member this.SetLocation location =
        this.transform.localPosition <- location

    member this.SpriteView =
        this.GetComponent<SpriteView> ()

    override this.SetState state =
        state.Location |> locationToVector3 |> this.SetLocation
        this.SpriteView.SetSprite state.Sprite

type EntityViewPool () =
    inherit ViewPool<IState, EntityView> ("Entity", "Entities", 50)

    member this.Update states = this.SetStates states

Store entity state in a union or record and have it implement the interface. The actual logic should be stored in a module (sprites definitely need to be in an asset module), but I have everything in the methods to simplify the example.

Code:
type Fighter =
    | Stand of Frame
    | Throw of Frame
    | Dead

    static member Start = Stand 0 :> IState

    interface IState with

        member this.Next gamepad =
            
            let stand i =
                match i, gamepad with
                | _, (true, _) -> Throw 0
                | 60, _ -> Stand 0
                | i, _ -> Stand (i + 1)

            let throw =
                function
                | 60 -> Stand 0
                | i -> Throw (i + 1)

            let dead = Dead

            match this with
            | Stand i -> stand i
            | Throw i -> throw i
            | Dead -> dead
            :> IState
        
        member this.Location = 0.0, 0.0

        member this.Sprite =

            let load path = Resources.Load<Sprite> ("Sprites/Fighter/" + path)
        
            let stand =
            
                let a = load "StandA"
                let b = load "StandB"
                let c = load "StandC"

                function
                | i when i < 15 -> a
                | i when i < 30 -> b
                | i when i < 45 -> c
                | _ -> b

            let throw =
            
                let a = load "ThrowA" 
                let b = load "ThrowB"
                let c = load "ThrowC"
                let d = load "StandB"

                function
                | i when i < 10 -> a
                | i when i < 20 -> b
                | i when i < 45 -> c
                | _ -> d

            let dead = load "Dead"

            match this with
            | Stand i -> stand i
            | Throw  i-> throw i
            | Dead -> dead
 

Koren

Member
Well, Microsoft just bought Xamarin so I think eventually you'll be able to use Visual Studio to easily write Android projects in C#. For now it might be easiest to just write some Java, it's not that bad especially if you already write C#.
I'm pretty sure each programmer has its strange idea, and my distaste for Java is on the verge of allergy, probably irrational (I even wish Scala or Clojure wouldn't use the jvm). I'm not that fond of C#, but still better.

Should I work for a company, it would be pretty different, but since I'm doing this just as a hobby, I still have the luxury of choosing the languages I prefer.

I tend to avoid VS, too.

I know, I'm strange, but aren't we all, at least a bit? ^_^

A huge thanks... Too busy now to enjoy it much, but I've saved the page, and I'm sure it'll be really useful when I find the time to get into it.
 
Second week of second programming class and feel like it's getting easier, but I can't quite figure this out. I'm printing the search results from an arraylist.

Code:
System.out.print("\nPlease enter number to search for : ");
			 us = stdIn.nextInt();


			 //for each loop to print search results
			 for (int s : ar1)
			 {
				 ar1Index++;

				//if statement for printing search results
				if(s == us)
				
				System.out.println("Search Value: " + s + " found at location: " + ar1Index + " in the unsorted array");
} //end for

If I leave it like this I get these results.
A959wW1.png


Nice output, but the instructor also wants it to return a not found message if you search for something that's not in the arraylist. So if I change the code adding an else.

Code:
System.out.print("\nPlease enter number to search for : ");
			 us = stdIn.nextInt();


			 //for each loop to print search results
			 for (int s : ar1)
			 {
				 ar1Index++;

				//if statement for printing search results
				if(s == us)
				{
				System.out.println("Search Value: " + s + " found at location: " + ar1Index + " in the unsorted array");
				}
				else
				{
				System.out.println("Search Value: " + us + " was not found");
				}
} //end for

It returns every element it searched.

YgYO75i.png


If I search for something not in the array it just says it wasn't found 10 times.
 

vypek

Member
Nice output, but the instructor also wants it to return a not found message if you search for something that's not in the arraylist. So if I change the code adding an else.

Code:
System.out.print("\nPlease enter number to search for : ");
			 us = stdIn.nextInt();


			 //for each loop to print search results
			 for (int s : ar1)
			 {
				 ar1Index++;

				//if statement for printing search results
				if(s == us)
				{
				System.out.println("Search Value: " + s + " found at location: " + ar1Index + " in the unsorted array");
				}
				else
				{
				System.out.println("Search Value: " + us + " was not found");
				}
} //end for

It returns every element it searched.

YgYO75i.png


If I search for something not in the array it just says it wasn't found 10 times.

It is saying that because you are outputting the not found message inside the loop. It would be better if you reported not found after the search is done (which means after the for loop has completed).

The original code you had can be kept the same to keep reporting if an element was found and at which index. But you should try out different logic for reporting if something was not found anywhere. Know what I mean?
 

Ledbetter

Member
Nice output, but the instructor also wants it to return a not found message if you search for something that's not in the arraylist. So if I change the code adding an else.

If I search for something not in the array it just says it wasn't found 10 times.

Instead of printing the "not found" message inside the for loop, you could use a boolean variable and change its value if the element was found or not. And check the variable value outside the for loop, that way you just print it once.
 
It is saying that because you are outputting the not found message inside the loop. It would be better if you reported not found after the search is done (which means after the for loop has completed).

The original code you had can be kept the same to keep reporting if an element was found and at which index. But you should try out different logic for reporting if something was not found anywhere. Know what I mean?



Instead of printing the "not found" message inside the for loop, you could use a boolean variable and change its value if the element was found or not. And check the variable value outside the for loop, that way you just print it once.

Alright thanks guys.
 
There's been a lot of talk about WebAssembly lately but I still don't quite get how it's supposed to work. How do you target web-specific structures such as the DOM from languages which have no concept of the DOM?

I'm talking out of my ass since I don't actually know, but presumably the DOM is "just some object", and WebAssembly contains instructions for accessing objects.
 

JeTmAn81

Member
I'm talking out of my ass since I don't actually know, but presumably the DOM is "just some object", and WebAssembly contains instructions for accessing objects.

That would make sense. I was having a hard time thinking of how they could make graphical interactions work as well but then I remembered WebGL exists and there must be huge API crossover between that and OpenGL. I also looked a bit into asm.js which is one of the inspirations for WebAssembly and it looks like it uses a strict subset of the JavaScript language so they may be staying away from the more browser-specific stuff.
 

Somnid

Member
There's been a lot of talk about WebAssembly lately but I still don't quite get how it's supposed to work. How do you target web-specific structures such as the DOM from languages which have no concept of the DOM?

You'll get a header file to work with and the compiler will fill those in for you.
 

injurai

Banned
I assumed WebAssembly was just going to be like a "byte code" specific to browsers. Where browsers basically have a VM designed specifically for the web. Then you can write languages to target WebAssembly instead of having everything target Javascript.
 

raphier

Banned
Is it? POPCNT, one assembly instruction. Or just use a lookup table.

Unless you are complaining that you're giving this as an interview question and nobody gets it right.

besides using buildin functions, try making one that can be used on multiple platforms, even the ones that have no SSE instructions. I've been fiddling around trying to build a solution without lookup tables and seander algorithms. bits may feel useless, but they do a performance increase in fingerprint recognition.
 
besides using buildin functions, try making one that can be used on multiple platforms, even the ones that have no SSE instructions. I've been fiddling around trying to build a solution without lookup tables and seander algorithms. bits may feel useless, but they do a performance increase in fingerprint recognition.

What's wrong with lookup tables? Not only is it trivially portable, and branchless, it's also the fastest possible architecture independent solution
 
What's wrong with lookup tables? Not only is it trivially portable, and branchless, it's also the fastest possible architecture independent solution
Cache invalidation?

Relevant for timing attacks in crypto -- practicing not relying on lookup tables is a worthwhile exercise just for that, IMO.

Probably relevant for context switching wrt NUMA shenanigans as well.

Why is it so hard to count bits branch free, ugh
I assume you know about this, but I will post it anyway:
http://graphics.stanford.edu/~seander/bithacks.html
 
Cache invalidation?

Lookup table can be 256 entries so essentially you're looking up 1 byte of your integer at a time. Each entry can only take on values from 0-8 inclusive so you require 4 bits per entry. So 2 entries per byte of lookup table, so 128 bytes needed for the lookup table. x86 has cache line of 64 bytes, so on average you're looking at about a 50% hit rate. In practice the numbers probably aren't too random, so the hit rate is probably going to be higher.

You can also test with a 32kb lookup table too (for looking up 2 bytes at a time), cache hit rate will be much lower but could still be faster since you'd be doing half as many lookups
 
So guys, I will start a cross platform project using C/C++ in my company. The objective is to create one application to run in multiples POS devices. Each vendor provides an API to communicate with their devices and the plan is to create an abstraction for those APIs. Does anyone have tips(articles, books...) to do it in the best way as possible?

You'll probably want to keep your business logic separated from the hardware specific stuff. You should write a hardware abstraction layer so that the low level stuff (file io/rendering) can be defined for each piece of hardware and the business level code doesn't care.

Well, Microsoft just bought Xamarin so I think eventually you'll be able to use Visual Studio to easily write Android projects in C#. For now it might be easiest to just write some Java, it's not that bad especially if you already write C#.

Xamarin is already a part of Visual studio, even before the purchase. You can actually write cross platform mobile apps in Visual Studio using C++/Xamarin C#/Unity C#/Cordova JavaScript.

https://www.visualstudio.com/en-us/features/mobile-app-development-vs.aspx

Although my person opinion is that Hybrid apps are awful and worse to maintain in the long run.
 

Koren

Member
Why is it so hard to count bits branch free, ugh
What is the size of your data?

How about, for a byte:
Code:
B = A & 0x55
A = A >> 1
A = A & 0x55
B = B + A

A = B & 0x33
B = B >> 2
B = B & 0x33
A = A + B

B = A & 0x0F
A = A >> 4
A = A & 0x0F
B = A + B

Works with every assembly, need only two registers, no loop/branch, scales easily for larger data, and it's log2(# bits)

Would that fit the bill?

Edit: if the only reason for avoiding LUT is cache invalidation, the solution above may not be faster... I just suggest it as a "no loop, no branch, no LUT, as-efficient-as-possible" solution.

Even more when LUT[A & 0xF] + LUT[A >> 4] gives you a LUT solution that use a LUT long of 8 or 16 bytes only if you really want to avoid cache misses.
 
First time poster in this thread but I was wondering if anyone can help me with this demo test for school I've been struggling on. Coderunner is requiring very specific answers of only a function for a program that works out a quadratic. For example, here is another question I got correct:

Write a function IsLeapYear() to determine whether a given year is a leap year or not. The criterion for a leap year is:

1. If a year is evenly divisible by 400, then it is a leap year.
2. Otherwise, if a year is divisible by 100, then it is not a leap year.
3. The only other leap years are evenly divisible by 4.


bool IsLeapYear(int year){
if (year % 400 == 0) return true;
else if (year % 100 == 0) return false;
else if (year % 4 == 0) return true;
else return false;
}

The above code satisfied the requirements but the next one I'm finding a lot trickier as I'm not sure how to exactly give it what it wants. This is what it says:

Write a function quadratic() which determines the number of solutions of a quadratic equation whose coefficients are passed as parameters.

And this is what it expects as the output:

double a = 6, b = 4, c = -7;
if (quadratic(a,b,c) == 2) cout << "There are two roots";
else if (quadratic(a,b,c) == 1) cout << "There is one root";
else cout << "There is no root";


Sorry if any of this is unclear or messy but I'd appreciate any kind of help.
 

Koren

Member
Write a function quadratic() which determines the number of solutions of a quadratic equation whose coefficients are passed as parameters.
Is your problem math-related or implementation-related?

Just in case, remember that the number of solutions depends on the value of

b*b - 4*a*c

Positive, there's 2 solutions

Zero, there's 1

Negative, there's none.


It's just a matter of comparing b*b - 4*a*c to zero.


That being said, it's tricky with floats. Due to rounding errors, you can get wrong results if b*b - 4*a*c is close to 0, and there's not many things you can do (there is some, but it's not completely safe, and it can be quite difficult). You probably don't mind...

But I'd still say "One root" if b*b - 4*a*c is just "really close to 0", such as between -1e15 and 1e15.
 

raphier

Banned
First time poster in this thread but I was wondering if anyone can help me with this demo test for school I've been struggling on. Coderunner is requiring very specific answers of only a function for a program that works out a quadratic. For example, here is another question I got correct:

Write a function IsLeapYear() to determine whether a given year is a leap year or not. The criterion for a leap year is:

1. If a year is evenly divisible by 400, then it is a leap year.
2. Otherwise, if a year is divisible by 100, then it is not a leap year.
3. The only other leap years are evenly divisible by 4.


bool IsLeapYear(int year){
if (year % 400 == 0) return true;
else if (year % 100 == 0) return false;
else if (year % 4 == 0) return true;
else return false;
}

The above code satisfied the requirements but the next one I'm finding a lot trickier as I'm not sure how to exactly give it what it wants. This is what it says:

Write a function quadratic() which determines the number of solutions of a quadratic equation whose coefficients are passed as parameters.

And this is what it expects as the output:

double a = 6, b = 4, c = -7;
if (quadratic(a,b,c) == 2) cout << "There are two roots";
else if (quadratic(a,b,c) == 1) cout << "There is one root";
else cout << "There is no root";


Sorry if any of this is unclear or messy but I'd appreciate any kind of help.
330px-Quadratic_formula.svg.png



if b*b - 4ac > 0 two roots. b*b - 4ac == 0 one root. b*b - 4ac < 0 no roots.
 
Is your problem math-related or implementation-related?

Just in case, remember that the number of solutions depends on the value of

b*b - 4*a*c

Positive, there's 2 solutions

Zero, there's 1

Negative, there's none.


It's just a matter of comparing b*b - 4*a*c to zero.


That being said, it's tricky with floats. Due to rounding errors, you can get wrong results if b*b - 4*a*c is close to 0, and there's not many things you can do (there is some, but it's not completely safe, and it can be quite difficult). You probably don't mind...

But I'd still say "One root" if b*b - 4*a*c is just "really close to 0", such as between -1e15 and 1e15.

Thanks but I think I managed (with the help of youtube) to essentially do the same thing in a regular program which I'll paste below but I don't know how to convert it into just a function and give coderunner what it wants in a similar fashion to the previous example I showed.

#include <iostream>
#include <cmath>
using namespace std;

int main(int argc, char** argv) {

double root1, root2, a, b, c, root;
// Ax^2 + Bx +C = 0

cout << "Enter coefficients: a, b and c ";
cin >> a >> b >> c;

root = sqrt(b * b - 4.0 * a * c);
root1 = -0.5 * (root + b)/a;
root2 = 0.5 * (root - b)/a;

if (root == 0)
{
cout << "There is one root: ";
}
else if (root >0)
{
cout << "There are two roots: ";
}
else
{
cout << "There is no solution";
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(4);
cout << "x1 = " << root1 << " and x2 = " << root2 << "\n";
return 0;
}
 

Koren

Member
Thanks but I think I managed (with the help of youtube) to essentially do the same thing in a regular program which I'll paste below but I don't know how to convert it into just a function and give coderunner what it wants in a similar fashion to the previous example I showed.
You're trying to compute the roots. You shouldnt, since you just have to return the *number* of roots.

Here
Code:
    root = sqrt(b * b - 4.0 * a * c);
You'll get issues whe b*b - 4*a*c < 0 since sqrt don't work with negative values.

Don't take the sqrt, just check the sign!


Beside, if I understood correctly, you function should either return 0, 1 or 2. It shouldn't display anything.
 

Koren

Member
Just to be more clear... (or so I hope)

Code:
#include <iostream>
#include <cmath>
using namespace std;




// The function you have to complete:

int quadratic(double a, double b, double c) {
   
    double discr = b*b - 4.0*a*c;

    if (something)
        return 2;

    if (something)
        return 1;

    return 0;
}


// A "main" for testing it:

int main(int argc, char** argv) {
    double a, b, c;
    // Ax^2 + Bx +C = 0

    cout << "Enter coefficients: a, b and c ";
    cin >> a >> b >> c;

    if (quadratic(a,b,c) == 2)
        cout << "There are two roots";
    else if (quadratic(a,b,c) == 1)
        cout << "There is one root";
    else
        cout << "There is no root";

    return 0;
}

Edit: it's pretty stupid to do two calls to quadratic with the same parameters (I'm battling with my students against this), but if I understand well, it's in the question, so I've left it unchanged...
 

raphier

Banned
What is the size of your data?

Works with every assembly, need only two registers, no loop/branch, scales easily for larger data, and it's log2(# bits)

Would that fit the bill?

Edit: if the only reason for avoiding LUT is cache invalidation, the solution above may not be faster... I just suggest it as a "no loop, no branch, no LUT, as-efficient-as-possible" solution.

Even more when LUT[A & 0xF] + LUT[A >> 4] gives you a LUT solution that use a LUT long of 8 or 16 bytes only if you really want to avoid cache misses.

The system I have is an older ARM architecture which operates on few instructions and has no memory, but saves and loads on memory. my Data is in gigabyte on a harddrive. this is why I cannot use tables, I reserve all I have on data that I put through minimal instruction set as possible, but fast as possible, couple of bytes at a time. stupid budget computation projects. And the way branches work, they are not realiable on older systems, the system may think that it has to create a new branching then abandon the other one, resulting in wrong answers.

Your example is the seander algorithm. I tried it, but I still need to reduced with one less instruction.
 
Thanks for being patient with me. I tried the function you provided and changed it around a little bit and I think I'm finally getting somewhere because this is the first time I actually got some feedback for my error. The text below is what it wanted to check.

double a = 6, b = 4, c = -7;
if (quadratic(a,b,c) == 2) cout << "There are two roots";
else if (quadratic(a,b,c) == 1) cout << "There is one root";
else cout << "There is no root";

And this was the result.

Expected
There are two roots

Got
There is no root

And this is the code I entered.

int quadratic(double a, double b, double c){
double discr = b*b - 4.0*a*c;
if (discr == 2) return 2;
else if (discr == 1) return 1;
else return 0;
}

EDIT: Oh I just changed the '== 2' and '== 1' to '> 0' and '== 0' respectively and it worked. Thanks for all the help again.
 

Koren

Member
this is why I cannot use tables
Even a 8 bytes long table? That's harsh...

Your example is the seander algorithm. I tried it, but I still need to reduced with one less instruction.
You need a shorter solution (in term of number or instructions)? Without lut and tests?

Seems awfully tricky to achieve...

You'll need only 20 instructions for 32 bits words, still not "short enough"?
 

iapetus

Scary Euro Man
popcount_2, maybe, yes... It's a variation of the same algorithm, but it spares 2 instructions for 8 bits values, at the cost of some readability. If it's really a matter of a single instruction, it may fit raphier requirements.

(If the hardware is old, I doubt multiplication is usable)

Yeah, most old ARM chipsets don't do multiplication well. But readability isn't likely to be an issue here, and that's a clever variation that would probably work well on ARM.
 
Top Bottom